内容简介:翻译:疯狂的技术宅来源:
每日前端夜话 0x7D
每日前端夜话,陪你聊前端。
每天晚上18:00准时推送。
正文共:3509 字
预计阅读时间: 10 分钟
翻译:疯狂的技术宅
来源: toptal
概述
在 React 16 中为了防止不必要的 DOM 更新,允许你决定是否让 .setState
更来新状态。在调用 .setState
时返回 null
将不再触发更新。
我们将通过重构一个 mocktail (一种不含酒精的鸡尾酒)选择程序来探索它是如何工作的,即使我们选择相同的 mocktail 两次也会更新。
目录结构如下所示:
1src 2 |-> App.js 3 |-> Mocktail.js 4 |-> index.js 5 |-> index.css 6 |-> Spinner.js
我们的程序如何工作
我们的程序将显示一个被选中的 mocktail。可以通过单击按钮来选择或切换 mocktail。这时会加载一个新的 mocktail,并在加载完成后渲染出这个 mocktail 的图像。
App
组件的父组件有 mocktail
状态和 updateMocktail
方法,用于处理更新 mocktail。
1import React, { Component } from 'react'; 2 3import Mocktail from './Mocktail'; 4 5class App extends Component { 6 7 state = { 8 mocktail: '' 9 } 10 11 updateMocktail = mocktail => this.setState({ mocktail }) 12 13 render() { 14 15 const mocktails = ['Cosmopolitan', 'Mojito', 'Blue Lagoon']; 16 17 return ( 18 <React.Fragment> 19 <header> 20 <h1>Select Your Mocktail</h1> 21 <nav> 22 { 23 mocktails.map((mocktail) => { 24 return <button 25 key={mocktail} 26 value={mocktail} 27 type="button" 28 onClick={e => this.updateMocktail(e.target.value)}>{mocktail}</button> 29 }) 30 } 31 </nav> 32 </header> 33 <main> 34 <Mocktail mocktail={this.state.mocktail} /> 35 </main> 36 </React.Fragment> 37 ); 38 } 39} 40 41export default App;
在 button
元素的 onClick
事件上调用 updateMocktail
方法, mocktail
状态被传递给子组件 Mocktail
。
Mocktail
组件有一个名为 isLoading
的加载状态,当其为 true
时会渲染 Spinner
组件。
1import React, { Component } from 'react'; 2 3import Spinner from './Spinner'; 4 5class Mocktail extends Component { 6 7 state = { 8 isLoading: false 9 } 10 11 componentWillReceiveProps() { 12 this.setState({ isLoading: true }); 13 setTimeout(() => 14 this.setState({ 15 isLoading: false 16 }), 500); 17 } 18 19 render() { 20 21 if (this.state.isLoading) { 22 return <Spinner/> 23 } 24 25 return ( 26 <React.Fragment> 27 <div className="mocktail-image"> 28 <img src={`img/${this.props.mocktail.replace(/ +/g, "").toLowerCase()}.png`} alt={this.props.mocktail} /> 29 </div> 30 </React.Fragment> 31 ); 32 } 33} 34 35export 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
值为其赋值。
1updateMocktail = mocktail => { 2 const newMocktail = mocktail; 3 this.setState({ 4 mocktail 5 }) 6}
因为我们需要基于之前的状态检查和设置状态,而不是传递 setState
和 object
,所以我们需要传递一个以前的状态作为参数的函数。然后检查 mocktail
状态的新值是否与现有值相同。
如果值相同, setState
将返回 null
。否则 setState
返回更新的 mocktail
状态,这将触发使用新状态重新渲染 Mocktail
组件。
1updateMocktail = mocktail => { 2 const newMocktail = mocktail; 3 this.setState(state => { 4 if (state.mocktail === newMocktail) { 5 return null; 6 } else { 7 return { mocktail }; 8 } 9 }) 10}
现在单击按钮仍会加载其各自的 mocktail 图像。但是,如果我们再次单击同一个mocktail按钮,React 不会重新渲染 Mocktail
组件,因为 setState
返回 null
,所以状态没有改变,也就不会触发更新。
我在下面的两个 GIF 中突出显示了 React DevTools 中的更新:
注意:我在这里换了一个深色主题,以便更容易观察到 React DOM 中的更新。
总结
本文介绍了在 React 16 中怎样从 setState
返回 null
。我在下面的 CodeSandbox
中添加了 mocktail
选择程序的完整代码,供你使用和 fork。
CodeSandbox:https://codesandbox.io/embed/vj8wk0mzjy
通过使用 null
可以防止不必要的状态更新和重新渲染,这样使我们的程序执行得更快,从而改善程序的用户体验。
用户偶然发现我们的产品,他们对产品的看法直接反映了对公司及其产品的看法,因此我们需要以自然和直观的方式围绕用户的期望去构建体验。
希望本文能够对你有所帮助。感谢阅读!
原文:https://blog.logrocket.com/returning-null-from-setstate-in-react-16-5fdb1c35d457/
图书推荐
下面夹杂一些私货:也许你和高薪之间只差这一张图
2019年京程一灯课程体系上新,这是我们第一次将全部课程列表对外开放。
愿你有个好前程,愿你月薪30K。我们是认真的 !
在公众号内回复“体系”查看高清大图
长按二维码,加大鹏老师微信好友
拉你加入前端技术交流群
唠一唠怎样才能拿高薪
往期精选
小手一抖,资料全有。长按二维码关注 前端先锋 ,阅读更多技术文章和业界动态。
以上所述就是小编给大家介绍的《在 React 16 中从 setState 返回 null 的妙用[每日前端夜话0x7D]》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。