翻译:疯狂的技术宅原文:https://blog.logrocket.com/re...css
未经容许严禁转载前端
在 React 16 中为了防止没必要要的 DOM 更新,容许你决定是否让 .setState
更来新状态。在调用 .setState
时返回 null
将再也不触发更新。react
咱们将经过重构一个 mocktail (一种不含酒精的鸡尾酒)选择程序来探索它是如何工做的,即便咱们选择相同的 mocktail 两次也会更新。程序员
目录结构以下所示:面试
src |-> App.js |-> Mocktail.js |-> index.js |-> index.css |-> Spinner.js
咱们的程序将显示一个被选中的 mocktail。能够经过单击按钮来选择或切换 mocktail。这时会加载一个新的 mocktail,并在加载完成后渲染出这个 mocktail 的图像。segmentfault
App
组件的父组件有 mocktail
状态和 updateMocktail
方法,用于处理更新 mocktail。bash
import React, { Component } from 'react'; import Mocktail from './Mocktail'; class App extends Component { state = { mocktail: '' } updateMocktail = mocktail => this.setState({ mocktail }) render() { const mocktails = ['Cosmopolitan', 'Mojito', 'Blue Lagoon']; return ( <React.Fragment> <header> <h1>Select Your Mocktail</h1> <nav> { mocktails.map((mocktail) => { return <button key={mocktail} value={mocktail} type="button" onClick={e => this.updateMocktail(e.target.value)}>{mocktail}</button> }) } </nav> </header> <main> <Mocktail mocktail={this.state.mocktail} /> </main> </React.Fragment> ); } } export default App;
在 button
元素的 onClick
事件上调用 updateMocktail
方法,mocktail
状态被传递给子组件 Mocktail
。服务器
Mocktail
组件有一个名为 isLoading
的加载状态,当其为 true
时会渲染 Spinner
组件。微信
import React, { Component } from 'react'; import Spinner from './Spinner'; class Mocktail extends Component { state = { isLoading: false } componentWillReceiveProps() { this.setState({ isLoading: true }); setTimeout(() => this.setState({ isLoading: false }), 500); } render() { if (this.state.isLoading) { return <Spinner/> } return ( <React.Fragment> <div className="mocktail-image"> <img src={`img/${this.props.mocktail.replace(/ +/g, "").toLowerCase()}.png`} alt={this.props.mocktail} /> </div> </React.Fragment> ); } } export default Mocktail;
在 Mocktail
组件的 componentWillReceiveProps
生命周期方法中调用 setTimeout
,将加载状态设置为 true
达 500 毫秒。多线程
每次使用新的 mocktail
状态更新 Mocktail
组件的 props 时,它会用半秒钟显示加载动画,而后渲染 mocktail 图像。
如今的问题是,即便状态没有改变,mocktail
状态也会被更新,同时触发从新渲染 Mocktail
组件。
例如每当单击 Mojito 按钮时,咱们都会看到程序对 Mojito 图像进行了没必要要地从新渲染。 React 16 对状态性能进行了改进,若是新的状态值与其现有值相同的话,经过在 setState
中返回 null
来防止来触发更新。
如下是咱们将要遵循的步骤,来防止没必要要的从新渲染:
null
null
将不会更新状态和触发组件从新渲染首先,在 app
组件的 updateMocktail
方法中,建立一个名为 newMocktail
的常量,并用传入的 mocktail
值为其赋值。
updateMocktail = mocktail => { const newMocktail = mocktail; this.setState({ mocktail }) }
由于咱们须要基于以前的状态检查和设置状态,而不是传递 setState
和 object
,因此咱们须要传递一个之前的状态做为参数的函数。而后检查 mocktail
状态的新值是否与现有值相同。
若是值相同,setState
将返回 null
。不然 setState
返回更新的 mocktail
状态,这将触发使用新状态从新渲染 Mocktail
组件。
updateMocktail = mocktail => { const newMocktail = mocktail; this.setState(state => { if (state.mocktail === newMocktail) { return null; } else { return { mocktail }; } }) }
如今单击按钮仍会加载其各自的 mocktail 图像。可是,若是咱们再次单击同一个mocktail按钮,React 不会从新渲染 Mocktail
组件,由于 setState
返回 null
,因此状态没有改变,也就不会触发更新。
我在下面的两个 GIF 中突出显示了 React DevTools 中的更新:
<center>没有从 setState 返回 null</center>
<center>从 setState 返回 null 以后</center>
注意:我在这里换了一个深色主题,以便更容易观察到 React DOM 中的更新。
本文介绍了在 React 16 中怎样从 setState
返回 null
。我在下面的 CodeSandbox
中添加了 mocktail
选择程序的完整代码,供你使用和 fork。
CodeSandbox:https://codesandbox.io/embed/...
经过使用 null
能够防止没必要要的状态更新和从新渲染,这样使咱们的程序执行得更快,从而改善程序的用户体验。
用户偶然发现咱们的产品,他们对产品的见解直接反映了对公司及其产品的见解,所以咱们须要以天然和直观的方式围绕用户的指望去构建体验。
但愿本文可以对你有所帮助。感谢阅读!