React 中 render 函数的执行时机

8,286 阅读2分钟

学习 React 已快有 3 个月了,在这里通过分享学习心得,与大家一起交流,与大家一起每天进步。

在刚开始学习 React 的时候,我认为组件的 state 或者 props 改变时,就会触发组件的 render 函数执行。后来我通过一系列的试验发现,state 不改变也可以触发 render 函数的执行,props 改变了也不一定触发 render 函数的执行,下面通过一系列的 demo 说明这个观点。

state不改变也可以触发render函数的执行

直接上代码:

import React from 'react';
import ReactDOM from 'react-dom';

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            message: 'click button',
        };
        this.handleClick = this.handleClick.bind(this);
    }

    handleClick() {
        console.log('Click happen');
        this.setState({});
    }

    render() {
        console.log('App render');
        const { message } = this.state;
        return (
            <button onClick={ this.handleClick }>{ message }</button>
        );
    }
}

ReactDOM.render(<App />, document.getElementById('root'));

代码的思路很简单,按钮绑定一个点击事件,当点击按钮时,执行 setState({}) 方法,由于 setState 方法的参数是一个空对象,state 并没有改变,这时候观察 render 函数是否执行,结果是执行了的,如下图,所以,只要 setState 方法执行,render 函数就会执行。

setState({})执行结果

props改变了也不一定触发render函数的执行

直接上代码:

import React, {Fragment} from 'react';
import ReactDOM from 'react-dom';

const obj = {
    message: 'hello world',
};

class App extends React.Component {
    handleClick() {
        console.log('click happen');
        obj.message = 'hello Beijing';
    }

    render() {
        return (
            <Fragment>
                <button onClick={ this.handleClick }>Click</button>
                <Component1 objMessage={ obj } />
            </Fragment>
        );
    }
}

class Component1 extends React.Component {
    render() {
        const { objMessage } = this.props;
        console.log('Component1 render');
        return (
            <div>{ objMessage.message }</div>
        );
    }
}

ReactDOM.render(<App />, document.getElementById('root'));

代码思路很简单,一个父组件 App,一个子组件 Component1,子组件的props来自于外部变量 obj,当我点击父组件的按钮时,去改变外部变量 obj 对象的值,这时候去观察子组件 Component1 的 render 函数是否执行,结果是没有执行,如下图,所以 props 改变了也不一定触发 render 函数的执行。

props改变

总结

在 React 中,只要执行了 setState 方法,就一定会触发 render 函数执行;组件的 props 改变了,不一定触发 render 函数的执行,除非 props 的值来自于父组件或者祖先组件的 state,在这种情况下,组件的 props 改变,也就意味着父组件或者祖先组件的 state 发生了改变,也就是父组件或者祖先组件执行了 setState 方法;那么可以总结出,render 函数的执行时机就是 setState 方法的执行。

另,render 函数执行并不一定意味着发生 DOM 操作,render 函数执行只是返回虚拟 DOM,需要通过比较新旧虚拟 DOM 来决定是否发生 DOM 操作,新旧虚拟 DOM 的比较,就涉及 diff 算法了,这又是另一个话题了。