哪些方法会触发 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. 调用生命周期方法(类组件)
    在类组件中,重新渲染时会依次触发一些生命周期方法,比如 componentWillUpdateshouldComponentUpdaterendercomponentDidUpdate

详细讲解与拓展

  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>;
    }

    “`

  • forceUpdateforceUpdate 是类组件中一个特殊的 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 来高效地管理界面更新。

发表评论

后才能评论