ReactJS-每次调用“ setState”时都会调用渲染吗?

每次setState调用时,React都会重新渲染所有组件和子组件吗?

如果是这样,为什么?我以为这个想法是,当状态改变时,React只渲染所需的内容。

在下面的简单示例中,尽管onClick处理程序始终将设置state为相同的值,但是在随后的单击中状态不会改变,这两个类在单击文本时都再次呈现。

this.setState({'test':'me'});

我曾希望只有在state数据更改的情况下才会进行渲染

这是示例代码,例如JS Fiddle和嵌入式代码段:

var TimeInChild = React.createClass({
    render: function() {
        var t = new Date().getTime();

        return (
            <p>Time in child:{t}</p>
        );
    }
});

var Main = React.createClass({
    onTest: function() {
        this.setState({'test':'me'});
    },

    render: function() {
        var currentTime = new Date().getTime();

        return (
            <div onClick={this.onTest}>
            <p>Time in main:{currentTime}</p>
            <p>Click me to update time</p>
            <TimeInChild/>
            </div>
        );
    }
});

ReactDOM.render(<Main/>, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react-dom.min.js"></script>

[1]: http://jsfiddle.net/fp2tncmb/2/
DavaidHarry2020/03/09 23:22:45

“丢失更新”的另一个原因可能是下一个:

如果是问题,则U可以避免在更新过程中设置状态,您应该像这样检查状态参数值

static getDerivedStateFromProps(props: TimeCorrectionProps, state: TimeCorrectionState): TimeCorrectionState {
   return state ? state : {disable: false, timeCorrection: props.timeCorrection};
}

另一种解决方案是在状态中添加一个初始化的属性,并在第一次设置它(如果状态被初始化为非空值)。

樱LEY神无2020/03/09 23:22:45

每次调用setState时,React都会重新渲染所有组件和子组件吗?

默认情况下-是。

有一个方法boolean shouldComponentUpdate(object nextProps,object nextState),每个组件都有此方法,它负责确定“组件应该更新(运行渲染功能)吗?”。每次更改状态从父组件传递新的道具时

您可以为组件编写自己的shouldComponentUpdate方法实现,但是默认实现始终返回true-意味着始终重新运行渲染函数。

引用官方文档http://facebook.github.io/react/docs/component-specs.html#updating-shouldcomponentupdate

默认情况下,在状态发生适当变化时,shouldComponentUpdate始终返回true以防止细微的错误,但是如果您始终将状态视为不可变并在render()中对props和state进行只读处理,则可以使用比较旧道具和状态及其替换的实现。

问题的下一部分:

如果是这样,为什么?我认为这个想法是,当状态改变时,React只渲染所需的内容。

我们可以将“渲染”分为两个步骤:

  1. 虚拟DOM渲染:调用render方法时,它将返回组件的新虚拟dom结构。如前所述,此渲染方法总是在调用setState()时调用,因为默认情况下shouldComponentUpdate始终返回true。因此,默认情况下,React中没有优化。

  2. 原生DOM渲染:只有在虚拟DOM中更改了真实DOM节点后,React才更改浏览器中的真实DOM节点,并且需要的次数很少-这就是React的一项出色功能,它可以优化真实DOM变异并加快React的速度。

entaseven2020/03/09 23:22:45

不,状态改变时,React不会渲染所有内容。

  • 每当组件变脏(状态更改)时,都会重新渲染该组件及其子代。在某种程度上,这是要尽可能少地重新渲染。不调用render的唯一时间是将某个分支移到另一个根目录,从理论上讲,我们不需要重新渲染任何东西。在您的示例中,TimeInChild是的子组件Main,因此在状态Main更改时也会重新呈现

  • React不比较状态数据。setState被调用时,它标记组件为脏(这意味着它需要重新呈现)。需要注意的重要一点是,尽管render调用了组件的方法,但是仅当输出与当前DOM树不同(也就是在虚拟DOM树和文档的DOM树之间进行区分)时,才更新实际DOM。在您的示例中,即使state数据没有更改,上次更改的时间也发生了更改,从而使Virtual DOM与文档的DOM有所不同,因此更新了HTML。

Stafan逆天2020/03/09 23:22:45

是。每当“ shouldComponentUpdate”返回false时,它将每次调用setState时调用render()方法。

前端MandyJinJin2020/03/09 23:22:45

并非所有组件。

state组分看起来像整个APP的状态的瀑布的来源。

因此更改发生在setState调用的位置。renders然后从那里叫如果您使用的是纯组分,render则将被跳过。