在 React 16 中从 setState 返回 null 的妙用[每日前端夜话0x7D]

栏目: 服务器 · 发布时间: 5年前

内容简介:翻译:疯狂的技术宅来源:

每日前端夜话 0x7D

每日前端夜话,陪你聊前端。

每天晚上18:00准时推送。

正文共:3509 字

预计阅读时间: 10 分钟

翻译:疯狂的技术宅

来源: toptal

在 React 16 中从 setState 返回 null 的妙用[每日前端夜话0x7D]

概述

在 React 16  中为了防止不必要的 DOM 更新,允许你决定是否让 .setState 更来新状态。在调用 .setState 时返回   null 将不再触发更新。

我们将通过重构一个 mocktail (一种不含酒精的鸡尾酒)选择程序来探索它是如何工作的,即使我们选择相同的 mocktail 两次也会更新。

在 React 16 中从 setState 返回 null 的妙用[每日前端夜话0x7D]
我们的 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 来防止来触发更新。

在 React 16 中从 setState 返回 null 的妙用[每日前端夜话0x7D]

解决方案

以下是我们将要遵循的步骤,来防止不必要的重新渲染:

  1. 检查新的状态值是否与现有值相同

  2. 如果值相同,我们将返回 null

  3. 返回 null 将不会更新状态和触发组件重新渲染

首先,在 app 组件的 updateMocktail 方法中,创建一个名为 newMocktail 的常量,并用传入的 mocktail 值为其赋值。

1updateMocktail = mocktail => {  
2  const newMocktail = mocktail;    
3  this.setState({     
4    mocktail  
5  })  
6}

因为我们需要基于之前的状态检查和设置状态,而不是传递 setStateobject ,所以我们需要传递一个以前的状态作为参数的函数。然后检查 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}
在 React 16 中从 setState 返回 null 的妙用[每日前端夜话0x7D]

现在单击按钮仍会加载其各自的 mocktail 图像。但是,如果我们再次单击同一个mocktail按钮,React 不会重新渲染 Mocktail 组件,因为 setState 返回 null ,所以状态没有改变,也就不会触发更新。

我在下面的两个 GIF 中突出显示了 React DevTools 中的更新:

在 React 16 中从 setState 返回 null 的妙用[每日前端夜话0x7D]
没有从 setState 返回 null
在 React 16 中从 setState 返回 null 的妙用[每日前端夜话0x7D]
从 setState 返回 null 之后

注意:我在这里换了一个深色主题,以便更容易观察到 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]

在 React 16 中从 setState 返回 null 的妙用[每日前端夜话0x7D]

在公众号内回复“体系”查看高清大图

长按二维码,加大鹏老师微信好友

拉你加入前端技术交流群

唠一唠怎样才能拿高薪

在 React 16 中从 setState 返回 null 的妙用[每日前端夜话0x7D]

小手一抖,资料全有。长按二维码关注 前端先锋 ,阅读更多技术文章和业界动态。

在 React 16 中从 setState 返回 null 的妙用[每日前端夜话0x7D]


以上所述就是小编给大家介绍的《在 React 16 中从 setState 返回 null 的妙用[每日前端夜话0x7D]》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

设计模式之禅

设计模式之禅

秦小波 / 机械工业出版社 / 2010年3月 / 69.00元

如果说“四人帮”的《设计模式》是设计模式领域的“圣经”,那么之后出版的各种关于设计模式的书都可称之为“圣经”的“注释版”或“圣经的故事”。本书是得道者对“圣经”的“禅悟”,它既不像“圣经”那样因为惜字如金、字字珠玑而深奥、晦涩和难懂,又比“圣经”的“注释版”更深刻和全面、更通俗和生动、更接近开发者遇到的实践场景,更具指导性。本书兼收并蓄、博采众长,也许是设计模式领域里的下一个里程碑之作。 全......一起来看看 《设计模式之禅》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

html转js在线工具
html转js在线工具

html转js在线工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具