服务器之家:专注于服务器技术及软件下载分享
分类导航

node.js|vue.js|jquery|angularjs|React|json|js教程|

服务器之家 - 编程语言 - JavaScript - React - 详解React中的不可变值

详解React中的不可变值

2022-02-27 17:15一个前端王 React

这篇文章主要介绍了React中的不可变值的相关资料,帮助大家更好的理解和学习使用react.js,感兴趣的朋友可以了解下

什么是不可变值

函数式编程是指程序里面的函数和表达式都能像数学中的函数一样,给定了输入值,输出是确定的。比如

?
1
2
3
let a = 1;
let b = a + 1;
=> a = 1  b = 2;

变量b出现,虽然使用了变量a的值,但是没有修改a的值。

再看我们熟悉的react中的代码,假如初始化了this.state = { count: 1 }

?
1
2
3
4
componentDidMount() {
    const newState = { ...state, count: 2 }; // { count: 2 }
    this.setState(newState);
}

虽然我们使用了this.state,但是没有修改this.state的引用地址和直接修改count的值,对待this.props也一样。

为什么使用不可变值

React官网中给出三点好处:

  • 简化复杂的功能

不可变性使得复杂的特性更容易实现。

  • 跟踪数据的改变

如果直接修改数据,那么就很难跟踪到数据的改变。跟踪数据的改变需要可变对象可以与改变之前的版本进行对比,这样整个对象树都需要被遍历一次。

跟踪不可变数据的变化相对来说就容易多了。如果发现对象变成了一个新对象,那么我们就可以说对象发生改变了。

  • 确定在 React 中何时重新渲染

不可变性最主要的优势在于它可以帮助我们在 React 中创建 pure components。我们可以很轻松的确定不可变数据是否发生了改变,从而确定何时对组件进行重新渲染。

React性能优化离不开不可变值

  • 首先,我们都知道,shouldComponentUpdate钩子函数默认返回true,即只要父组件更新,子组件一定更新。
  • shouldComponentUdpate中可以接收两个参数,nextProps和nextState,假如我们通过判断this.props.xxx和nextProps.xxx相等以及this.state.xxx与nextState.xxx相等,可以将返回值设置为false,说明此次并不需要更新子组件。
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class CounterButton extends React.Component {
  constructor(props) {
    super(props);
    this.state = {count: 1};
  }
 
  shouldComponentUpdate(nextProps, nextState) {
    if (this.props.color !== nextProps.color) {
      return true;
    }
    if (this.state.count !== nextState.count) {
      return true;
    }
    return false;
  }
 
  render() {
    return (
      <button
        color={this.props.color}
        onClick={() => this.setState(state => ({count: state.count + 1}))}>
        Count: {this.state.count}
      </button>
    );
  }
}
  • React v15.3新增加了一个PureComponent类,能够对props和state进行浅比较来减少render函数的执行次数,避免不必要的组件渲染,实现性能上的优化。
  • PureComponent是什么原理呢

我们知道JS中的变量类型分为基本类型(number、string、boolean、undefined、null、symbol)和引用类型(function、object、function),基本类型的值保存在栈内存当中,引用类型的值保存在堆内存当中,栈内存中只保存指向堆内存的引用。而浅比较就是只对栈内存中的数据进行比较。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class App extends PureComponent {
  state = {
    items: [1, 2, 3]
  }
  handleClick = () => {
    const { items } = this.state;
    items.pop();
    this.setState({ items });
  }
  render() {
    return (
        <div>
            <ul>
                {this.state.items.map(i => <li key={i}>{i}</li>)}
            </ul>
            <button onClick={this.handleClick}>delete</button>
        </div>
    )
  }
}

上边这个例子使用了PureComponent,而且只改变了数组items里的值,而没改变items的引用地址,所以认为items没有发生变化,不会触发render函数,不会触发组件的渲染。

如果想实现组件更新,可以按如下的方式,创建一个新的数组,将新数组的地址赋给items。

?
1
2
3
4
5
6
handleClick = () => {
    const { items } = this.state;
    items.pop();
    var newItem = [...items];
    this.setState({ item: newItem });
}
  • PureComponent帮我们做了浅层的比较,所以要注意state时尽量合理,如果需要出现引用嵌套引用的数据结构的话,可以配合Immutable.js。
  • 什么是Immutable

(1) Immutable是一旦创建,就不能被更改的数据。(2) 对Immutable对象的任何修改或添加删除操作都会返回一个新的Immutable对象。(3)Immutable实现的原理是Persistent Data Structure(持久化数据结构),也就是是永久数据创建新数据时,要保证旧数据同时可用且不变。(4)同时为了避免deepCopy把所有节点都复制一遍带来的性能损耗,Immutable使用了Structural Sharing(结构共享),即如果对象树结点发生变化,只修改这个结点和受它影响的父节点,其他结点进行共享。

详解React中的不可变值

最后,如果想要在组件层面进行浅比较,可以使用React.memo()函数

总结

其实还是官网说的不可变性的第三条优势,也是最主要的优势,就是不可变性可以帮助我们在React中使用PureComponent。我们可以很轻松的确定数据是否发生了改变,组件何时需要发生重新渲染。

如果我们改变了state的值,shouldComponentUpdate获取到当前state和nextState,或者props和nextProps比较出来的值都是完全一样的,都会返回false,即使我们做了setState的操作,UI也不会发生更新。

PureComponent最好是搭配Immutable.js进行使用,来达到性能优化的目的。

结合React.memo来避免没必要的组件的更新渲染。

以上就是详解React中的不可变值的详细内容,更多关于React中的不可变值的资料请关注服务器之家其它相关文章!

原文链接:https://juejin.cn/post/6949184783473704974

延伸 · 阅读

精彩推荐
  • React如何编写高性能的 React 代码:规则、模式、注意事项

    如何编写高性能的 React 代码:规则、模式、注意事项

    本文将通过逐步实现一个简单的应用来带大家看看如何编写编写高性能的 React 代码。...

    前端充电宝9602022-02-24
  • React详解react应用中的DOM DIFF算法

    详解react应用中的DOM DIFF算法

    这篇文章主要介绍了react应用中的DOM DIFF算法,帮助大家更好的理解和学习使用react,感兴趣的朋友可以了解下...

    time_w6212022-02-25
  • ReactReact Hook的使用示例

    React Hook的使用示例

    这篇文章主要介绍了React Hook的使用示例,帮助大家更好的理解和学习使用React,感兴趣的朋友可以了解下...

    鹏厂搬砖工7172022-02-23
  • ReactReact实现todolist功能

    React实现todolist功能

    这篇文章主要介绍了React实现todolist功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...

    一杯清泉7082021-12-21
  • React深入理解React Native核心原理(React Native的桥接(Bridge)

    深入理解React Native核心原理(React Native的桥接(Bridge)

    这篇文章主要介绍了深入理解React Native核心原理(React Native的桥接(Bridge),本文重点给大家介绍React Native的基础知识及实现原理,需要的朋友可以参考下...

    Gavell9552022-02-23
  • ReactReact使用emotion写css代码

    React使用emotion写css代码

    这篇文章主要介绍了React如何使用emotion写css代码,帮助大家更好的理解和学习使用React,感兴趣的朋友可以了解下...

    joychenke8172022-02-25
  • ReactWebpack3+React16代码分割的实现

    Webpack3+React16代码分割的实现

    这篇文章主要介绍了Webpack3+React16代码分割的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面...

    小叶子8812022-01-25
  • ReactVite搭建React项目的方法步骤

    Vite搭建React项目的方法步骤

    这篇文章主要介绍了Vite搭建React项目的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面...

    Cookieboty5152022-02-24