0
function UserCard({ user }) {
  let defaultUserName = user.nicknames[0];
  let [selectedNickname, setSelectedNickname] = React.useState(defaultUserName);

  // The selected nickname becomes invalid when the user is changed!!!
  const selectedNicknameIsValid = user.nicknames.includes(selectedNickname);

  return (<div>
     <UserCardWithNickName user={user} selectedNickname={selectedNickname} />
     <SelectNickName user={user} setSelectedNickname={setSelectedNickname} />
  </div>);

In the above snippet the component's state holds the selected nickname from the list of user nicknames. But when the user changes in the parent component this component is re-rendered with the same state. So the nickname in the state is for the wrong user.

What is the preferred way to handle this? A lot of google searching couldn't find much discussion.

Am I doing this in some fundamental non-react way?

Is the preferred solution to use useEffect to fix the state when it becomes invalid as discussed here React.useState does not reload state from props?

Working example on codesandbox

Jacob Stevenson
  • 3,718
  • 1
  • 13
  • 10
  • useEffect will re-render your component for new user, if you add user to its dependency array. Otherwise your component can't know, that it state should be updated. – Alex Tom May 11 '22 at 09:02

3 Answers3

0

Yeah, state changes in the parent component will usually re-render the child component, and hence reset the state of the child component. I'd suggest moving states that you want preserved up into the parent tree.

State management is an important concept in React. As your app grows, you'll realize doing this will add a lot of bloat and repetitive code. Learning about state management will prove very useful for you!

ad2969
  • 440
  • 3
  • 7
  • Thanks, but I think you misunderstood the question. The problem is that the state of the child component is *not* resetting. Re-rendering does not reset the state of the child component. Thanks for the link to the nice article. – Jacob Stevenson May 11 '22 at 14:05
0

Yes. The link you have posted is one way to do it. The question you have to look for is if your child component is managing the value of selectedNickname in anyway. That is the only reason you would want to keep it as a seperate state in the child component. If all it does is read the props from the parent, simply use the props and do not maintain an internal state at all.

Tushar Shahi
  • 16,452
  • 1
  • 18
  • 39
  • Yes, the child component is managing the state of selectedNickname which can be changed by the user. (my toy example leaves that part out) – Jacob Stevenson May 11 '22 at 13:57
0

Months later I finally found a robust discussion of this problem in the react docs.

https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html

The problem I was trying to describe is called derived state.

I eventually solved it by adding a key when using the component. When a key changes, React will create a new component instance rather than update the current one. This is one of the recommended approaches in the docs.

<UserCard user={user} key={user.id} />
Jacob Stevenson
  • 3,718
  • 1
  • 13
  • 10