reactjs - 当 child.shouldComponentUpdate() 返回 false 时,React useState() 钩子不会更新状态
问题描述
我已经开始阅读 React Hooks 并尝试重写一些小组件来使用它们,但是我在设置状态时遇到了问题。基本上,当子组件<Content/>
总是返回false
in 时shouldComponentUpdate
,父组件的 ( <App/>.setShow
) 会被调用,但它不会更新状态,<Content/>
也不会渲染。
我在下面准备了一个最小的工作示例,其中<App/>
是基于 React Hoos 的组件,并且<App2/>
是基于等效类的组件。后一个有效,所以显然我没有得到一些细微差别。
const {useState} = React;
class Panel extends React.Component {
shouldComponentUpdate() { return false; }
render() { return (<button onClick={this.props.onClick}>Toggle</button>) }
}
class Content extends React.Component {
render() { return <div>Content</div> }
}
const App = (props) => {
const [show, setShow] = useState(true);
const toggle = () => {
console.log("Toggling visibility!", show);
setShow(!show);
}
console.log("[App] render()");
return (<div >
<h1>Hi at {Date.now()}</h1>
<Panel onClick={toggle} />
{show && <Content /> }
</div>)
}
class App2 extends React.Component {
state = { show: true }
render() {
const toggle = () => {
console.log("[App] toggle", this.state.show)
this.setState({ show: !this.state.show })
}
console.log("[App] render()");
return (<div >
<h1>Hi at {Date.now()}</h1>
<Panel onClick={toggle} />
{this.state.show && <Content />}
</div>)
}
}
ReactDOM.render(<div> <App/> <App2/> </div>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<div id="app">
</app>
解决方案
您需要使用功能更新,因为您关闭了show
内部toggle
函数的值。
发生关闭是因为shouldComponentUpdate
总是返回false
,所以在第一次渲染时, 的值this.props.onClick
将具有 的陈旧状态show === true
,这在后续渲染中不会改变。
const App = () => {
const [show, setShow] = useState(true);
// Closure on value of show
// const toggle = () => {
// console.log("Toggling visibility!", show);
// setShow(!show);
// }
const toggle = () => {
setShow(prevState => {
console.log("Toggling visibility!", prevState);
return !prevState;
});
};
console.log("[App] render()");
return (
<div>
<h1>Hi at {Date.now()}</h1>
<Panel onClick={toggle} />
{show && <Content />}
</div>
);
};
推荐阅读
- postgresql - 在 Jelastic 上更改 PostgreSQL 节点上的 shared_buffers 值
- oracle - 如何检查 CLOB 列是否有非 ASCII 字符?
- regex - 使用 linux 工具将行从一种格式转换为另一种格式
- python - 在保持文件夹结构的同时读取图像
- sqlite - 在测试代码和被测试代码之间通过 Symfony2 功能测试共享数据库连接
- vim - 在 vimrc 中取消乳胶预览
- typescript - 打字稿和 ienumerators
- scala - 使用 Spark Scala 将数据转换为 MAP,如何?
- apache-karaf - IPOJO 组件未正确公开服务
- netflix-zuul - Zuul 块头