Reputation: 2191
I'm amazed that I can't solve this myself, but I'm having a basic issue here. Essentially I just want to destructure the user
variable in the useSetWelcome
hook to prevent the use of verbose chaining such as user.user.email
- for instance, const { email } = user
does not work and instead needs user.user.
I tried changing from const useSetWelcome = user => {
to const useSetWelcome = ({ user }) => {
, but that results in an infinite loop.
Where am I going wrong here? My code demo: https://stackblitz.com/edit/react-b1jroe
And the code:
import React, { useState, useEffect } from 'react';
const joe = {
name: 'Joe',
email: '[email protected]'
};
// const useSetWelcome = ({ user }) => { // infinite loop problem
const useSetWelcome = user => {
const [name, setName] = useState(null);
const [welcomeMsg, setWelcomeMsg] = useState('No user detected');
// const { email } = user; // needs user.user
// console.log('user', user);
// console.log('{user}', { user });
// console.log('user.email', user.email); // should be [email protected]
// console.log('email', email); // should be [email protected]
console.log('user?.user?.email', user?.user?.email); // works
if (user.name) {
setName(user.name);
setWelcomeMsg('welcome ' + user.name);
}
return { name, welcomeMsg };
};
const App = () => {
// const [user, setUser] = useState(joe); // joe or {joe}? and why?
const [user, setUser] = useState(joe);
console.log('state user', user);
const toggleLogin = user => {
if (user) {
setUser(null);
} else {
setUser(joe);
}
};
const loginMsg = user ? 'Logout' : 'Login';
const Welcome = user => {
const { name, welcomeMsg } = useSetWelcome(user);
return (
<p>
{welcomeMsg} {name}
</p>
);
};
return (
<div>
<Welcome user={user} />
<button onClick={() => toggleLogin(user)}>{loginMsg}</button>
</div>
);
};
export default App;
Upvotes: 0
Views: 710
Reputation: 2979
The problem is, <Welcome />
is a component. A component receives only one parameter, props
. So, when you write this: const Welcome = user => {
, its actually const Welcome = props => {
.
Long story short, change this line to const Welcome = ({ user }) => {
(so you destruct user
from props
) and it will work.
P.S.: You're getting an infinite loop because inside your useSetWelcome
hook, you have this condition:
if (user.name) {
setName(user.name)
}
When you use setName
, the entire hook rerenders, and the condition is tested again. Again, user.name
will exist, and setName
will get called again, and again, and forever. To achieve what I think you intended to, you have to improve the condition to something like this:
if (user.name && user.name !== name) {
setName(user.name);
setWelcomeMsg('welcome ' + user.name);
}
Upvotes: 3