反应:useState值不会在参数值更改时更新

时间:2020-07-24 23:04:22

标签: reactjs use-state

在下面的示例中,即使display参数在true和false之间切换,子组件上的show状态值也不会更新。

我希望它能够接收值并相应地进行更新。有人可以详细说明为什么它不起作用吗?

(我知道我可以在其中使用useEffect回调和setDisplay(show),但我想知道为什么这样的简单方法不起作用)

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>
  );
}

工作示例:https://codesandbox.io/s/react-boilerplate-4hexp?file=/src/index.js

3 个答案:

答案 0 :(得分:0)

好,仅在组件的第一个渲染上设置display的值(因为状态是state且state不会随渲染而改变,而是仅当您告诉它更改时才设置)。如果您希望它随着道具的变化而变化,只需使用一个普通常量即可。

答案 1 :(得分:0)

我相信这是因为子组件中的useState在首次加载时正在读取show,但由于它只是被设置,所以不会自动更新。

您可以直接使用show上的return show ? 'message' : <></>

或者您仍然可以将本地状态与useState一起使用,但是您需要添加useEffect来收听道具更改,然后更改该孩子的本地状态。

更新

当前代码正常工作的第三种选择是:

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

那样,当它为true时,组件将读取最新数据。

答案 2 :(得分:0)

displayChild的本地组件状态,在安装props.show时给定Child的初始值。 Child内永远不会进行状态更新以呈现display的任何其他值。实际上,这实际上是一种反模式,用于将传递的道具存储在本地组件状态中,但是有两种选择/解决方案来更新display

在道具更新时使用效果来更新状态

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

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

或者更好的是,直接食用道具show

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

后者的好处是show 的新值在相同的渲染周期中发生。使用前一种(反模式),状态需要先然后更新,然后重新渲染组件,因此更新的UI会延迟渲染周期。