在下面的示例中,即使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
答案 0 :(得分:0)
好,仅在组件的第一个渲染上设置display的值(因为状态是state且state不会随渲染而改变,而是仅当您告诉它更改时才设置)。如果您希望它随着道具的变化而变化,只需使用一个普通常量即可。
答案 1 :(得分:0)
我相信这是因为子组件中的useState
在首次加载时正在读取show
,但由于它只是被设置,所以不会自动更新。
您可以直接使用show
上的return show ? 'message' : <></>
或者您仍然可以将本地状态与useState
一起使用,但是您需要添加useEffect
来收听道具更改,然后更改该孩子的本地状态。
更新:
当前代码正常工作的第三种选择是:
{show && <Child show={show} />}
那样,当它为true时,组件将读取最新数据。
答案 2 :(得分:0)
display
是Child
的本地组件状态,在安装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会延迟渲染周期。