哪些方法会触发 React 重新渲染?重新渲染 render 会做些什么 ?

参考回答

触发 React 重新渲染的主要方法有:

  1. 改变组件的状态(state):
    当调用 setState(类组件)或 useState 的更新函数(函数组件)时,React 会重新渲染组件。例如,在函数组件中使用 useState 更新状态时,组件会重新渲染。

  2. 改变组件的属性(props):
    当父组件的 props 发生变化时,子组件会重新渲染。例如,当父组件传递给子组件的值发生变化时,子组件会自动重新渲染。

  3. 调用 forceUpdate(类组件):
    如果直接调用类组件的 forceUpdate 方法,即使状态或 props 没有变化,也会强制重新渲染组件。

  4. Context 变化:
    如果组件订阅了某个 React Context,当该 Context 的值发生变化时,所有使用该 Context 的组件都会重新渲染。

重新渲染(render)时做的事情:

  1. 重新计算虚拟 DOM:
    React 会根据最新的状态和 props 重新调用组件的 render 方法(对于类组件)或函数组件本身(对于函数组件),计算出一个新的虚拟 DOM(Virtual DOM)。

  2. 比较虚拟 DOM 和旧的虚拟 DOM:
    React 使用虚拟 DOM 来优化性能。在渲染过程中,React 会将新的虚拟 DOM 与之前的虚拟 DOM 进行比较,找出不同之处。

  3. 更新实际的 DOM:
    根据差异,React 会最小化地更新实际的浏览器 DOM,只改变那些变化了的部分,而不是重新渲染整个页面。

  4. 调用生命周期方法(类组件):
    在类组件中,重新渲染时会依次触发一些生命周期方法,比如 componentWillUpdate、shouldComponentUpdate、render 和 componentDidUpdate。

详细讲解与拓展

  1. 触发重新渲染的具体情况:
  • setState(类组件):setState 是更新组件状态的主要方法。当 setState 被调用时,React 会判断状态是否改变,如果改变,它会重新渲染该组件。

    “`javascript
    class Counter extends React.Component {
    state = { count: 0 };

    increment = () => {
    this.setState({ count: this.state.count + 1 });
    };

    render() {
    return <button onClick={this.increment}>Count: {this.state.count}</button>;
    }
    }

    “`
    每次点击按钮时,`increment` 会调用 `setState` 更新状态,触发重新渲染。

  • useState(函数组件):函数组件通过 useState 管理状态。调用 useState 的更新函数(例如 setCount)时,组件会重新渲染。

    “`javascript
    function Counter() {
    const [count, setCount] = useState(0);

    const increment = () => {
    setCount(count + 1);
    };

    return <button onClick={increment}>Count: {count}</button>;
    }

    “`
    每次点击按钮时,`increment` 会调用 `setCount` 更新状态,触发重新渲染。

  • 父组件传递的 props 变化:当父组件传递给子组件的 props 发生变化时,子组件会重新渲染。即使父组件没有调用 setState,只要 props 发生变化,子组件也会更新。

    “`javascript
    function Parent() {
    const [name, setName] = useState("Alice");

    return <Child name={name} />;
    }

    function Child(props) {
    return <h1>Hello, {props.name}</h1>;
    }

    “`

  • forceUpdate:forceUpdate 是类组件中一个特殊的 API,它会强制组件重新渲染,不管状态或 props 是否变化。

    “`javascript
    class MyComponent extends React.Component {
    forceReRender = () => {
    this.forceUpdate();
    };

    render() {
    return <button onClick={this.forceReRender}>Force Re-render</button>;
    }
    }

    “`

  • Context 变化:React Context 用来在组件树中共享数据。当 Context 的值发生变化时,所有订阅了该 Context 的组件都会重新渲染。

    “`javascript
    const MyContext = React.createContext();

    function Parent() {
    const [value, setValue] = useState("Hello");
    return (
    <MyContext.Provider value={value}>
    <Child />
    </MyContext.Provider>
    );
    }

    function Child() {
    const value = useContext(MyContext);
    return <h1>{value}</h1>;
    }

    “`

  1. 重新渲染的过程:
  • 重新计算虚拟 DOM:React 会在状态或 props 更新时,重新计算该组件的虚拟 DOM。虚拟 DOM 是 React 用来优化性能的机制,它是实际 DOM 的一个轻量级副本。
  • 比较虚拟 DOM 和旧的虚拟 DOM:React 会通过“Diffing算法”比较新旧虚拟 DOM,找出它们之间的差异,并生成更新的“补丁”。
  • 更新实际的 DOM:最后,React 会通过这些“补丁”来最小化地更新真实的 DOM。这样可以避免每次更新都重绘整个页面,从而提高性能。
  1. 生命周期方法(仅限类组件):
    • 在类组件中,每次重新渲染都会触发一些生命周期方法,通常这些方法有助于管理副作用或者控制渲染过程:
      • shouldComponentUpdate(nextProps, nextState):决定是否需要重新渲染。如果返回 false,React 会跳过渲染。
      • render():重新渲染组件的 UI。
      • componentDidUpdate(prevProps, prevState):在渲染完成后调用,可以在此方法中执行副作用操作。

总结

React 重新渲染的触发条件主要包括状态(state)、属性(props)、强制更新(forceUpdate)和 Context 变化。每次重新渲染时,React 会计算新的虚拟 DOM,与旧的虚拟 DOM 进行比较,并根据差异更新实际的 DOM。为了优化性能,React 尽量减少 DOM 的操作,使用虚拟 DOM 来高效地管理界面更新。

发表回复

后才能评论