在下面的示例中,当按钮被按下no
时,组件不会重绘(尽管状态中的值发生了变化)。很明显,这是因为对对象的引用obj
没有改变,PureComponent
只是在顶层值改变时才重绘。如果无法拒绝内部更改,如何使组件重新渲染?
class App extends React.PureComponent {
state = {
obj: { x: 10 }
}
render() {
return (
<p>
{this.state.obj.x}{" "}
<button onClick={this.no}>no</button>{" "}
<button onClick={this.ok}>ok</button>
</p>
)
}
no = () => {
var { obj } = this.state
++obj.x
this.setState({ obj })
}
ok = () => {
var { obj } = this.state
obj = { ...obj, x: obj.x+1 }
this.setState({ obj })
}
}
ReactDOM.render(<App />, document.querySelector("main"))
<script src="//cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<main></main>
在内部更改某些
state
内容是一种反模式,但如果由于某种原因无法摆脱它,您可以setState
使用forceUpdate
:如果你不知道返回的对象是
obj
新的还是修改的旧的,你可以使用在状态改变后调用的回调,但要注意这可能会导致双重重绘,所以我不建议这样做,除非绝对有必要:并且还值得考虑放弃 PureComponent 的选项 - 这样更新将在每次 setState 调用时发生(但也会在每次渲染父级时发生,因此性能可能会降低):
即使
PureComponent
你可以创建一个方法shouldComponentUpdate
来确定组件是否需要更新,尽管 React 会非常正确地发出警告,你不应该这样做 - 如果 PureComponent 的功能被完全重新定义,为什么还要编写它?