React单组件数据管理

222 阅读2分钟

一 什么时候会重新渲染UI

  1. 对于类组件,不管state变没变,只要调用了this.setState,就会重新render。
    因此类组件很容易有多余的render。shuouldComponentUpdate这个钩子可以解决该问题,可以在这个钩子里面对比新旧state以及新旧props,从而判断是否需要render。或者使用React.PureComponent也自带解决这个问题的功能, React.PureComponent中以浅层对比 (shallowEqual)prop 和 state的方式来实现了该函数。
  import React from 'react'

  class App extends React.Component{
    constructor(props){
      super(props);
      this.state={n:1};
    }

    add=()=>{
      //state没有变,但是setState了,所以每次都会打印render
      this.setState(this.state)
    }

    render(){
      console.log('render了');

      return(
        <>
          <div>{this.state.n}</div>
          <button onClick={this.add}>+1</button>
        </>
      )
    }
  }

  export default  App;

可以理解为,只要state传给this.setState之后,react都会把其值赋值给一个新的对象。因此类组件并不知道state是旧的引用还是新的引用,因为类组件的setState都会将传进来的旧引用变成一个新的引用。

  1. 对于函数组件,只有setState的参数的引用变了,才会重新render
  import React, { useState } from "react";

  export default function App() {
    const [data, setData] = useState({ n: 1 });

    const add = () => {
      //这样写会重新渲染
      // setData({ n: data.n + 1 });
      //这样写不会渲染,因为data的引用没有变
      //所以不要修改state!!!!!创建新的state
      //可以使用immer.js,创建新对象写起来就像是在修改原对象
      data.n+=1;
      setData(data);
    };

    console.log("render了");

    return (
      <div className="App">
        <div>{data.n}</div>
        <button onClick={add}>+1</button>
      </div>
    );
  }

二 总结

  1. state内容变了的时候。
    直接修改state,引用可以不变,不推荐。创建新对象,引用变化,会正常render。
  2. 什么时候render?
    类组件看到一个或多个setState就会render。函数组件发现state引用变了才会render。
  3. render做了什么?
    render会创建虚拟DOM,经过diff,最后选择性的更新真实DOM。
    所以多余的render很可能不会浪费多少性能。阻止render的代码如果写的太复杂了,可能比render还要耗性能。