AnswerBun.com

React: useState value doesn't update on parameter value change

In the example below, the value of the display state on Child component never updates, even if the show parameter toggles between true and false.

I expect it to receive the value and to update accordingly. Can someone please elaborate on why this is not working?

(I know I can use a useEffect callback and setDisplay(show) from inside it, but I’d like to know why a simpler approach like this doesn’t work)

function Child({ show }) {
  const [display] = React.useState(show);

  console.log({ show, display });
  return display ? "Message!" : null;
}

function Parent() {
  const [show, setShow] = React.useState(false);

  const handleClick = () => {
    setShow(!show);
  };

  return (
    <div>
      <div>
        <button onClick={handleClick}>Toggle</button>
      </div>
      <Child show={show} />
    </div>
  );
}

Working example: https://codesandbox.io/s/react-boilerplate-4hexp?file=/src/index.js

Stack Overflow Asked by darksoulsong on January 5, 2022

3 Answers

3 Answers

display is local component state of Child, given an initial value from props.show when Child mounted. There is never a state update within Child to render any other value of display. This is actually an anti-pattern to store passed props in local component state, but there are two alternatives/solutions to getting display to update.

Use an effect to update state when the props update

function Child({ show }) {
  const [display, setDisplay] = React.useState(show);
  useEffect(() => setDisplay(show), [show]);

  console.log(show, display);
  return display ? "Message!" : null;
}

Or better, just consume the prop show directly

function Child({ show }) {
  console.log(show);
  return show ? "Message!" : null;
}

The benefit of the latter is that the new value of show and the updated/rerendered UI occur in the same render cycle. With the former (the anti-pattern) the state needs to update then the component rerenders, so the updated UI is a render cycle delayed.

Answered by Drew Reese on January 5, 2022

I believe it's because the useState in the Child component is reading show when it first loads but then never updates because it's just set, it doesn't automatically update.

You could either just use show directly which should be used for return show ? 'message' : <></>

Or you could still use the local state with useState, but you would need to add a useEffect to listen to the props change then change the local state of that child.

Update:

Third option for your current code to work would also be to do:

{show && <Child show={show} />}

That way at the time when it's true, the component will read the latest data.

Answered by codingwithmanny on January 5, 2022

Well the value of display is set only on the first render of the component (because it is state and state doesnt change with renders, but only when you tell it to change). If you want it to be changing with changing props just use a normal constant instead.

Answered by Martin Červenka on January 5, 2022

Add your own answers!

Related Questions

Convert Array to string in Java/Groovy

5  Asked on January 26, 2021 by maaz

     

List of tuples remove duplicates by first index

3  Asked on January 26, 2021 by rankinstudio

   

Joining based on Sum of amount

1  Asked on January 26, 2021 by rohit-pandey

   

ARKit and Recording / Replaying Image+Depth with time lapse

0  Asked on January 26, 2021 by bsharer-app-share-books

   

Recognizing EOF vs newline in getline in C

3  Asked on January 26, 2021 by jan-dunder

       

How to Find Connected Components in dataset?

0  Asked on January 26, 2021 by mohamed-mohsen

       

Can’t get responses for intents in dialogflow using custom payloads

0  Asked on January 26, 2021 by luis-ramon-ramirez-rodriguez

   

How to initialize correctly an array with Array.CreateInstance() method

1  Asked on January 26, 2021 by donmiguelsan

 

Combine two list of map java 8

1  Asked on January 25, 2021 by jeeppp

     

Ask a Question

Get help from others!

© 2022 AnswerBun.com. All rights reserved.