嵌套setState是否有意义?

时间:2019-06-17 10:58:09

标签: reactjs react-native

我偶然发现了以下代码,我想知道它是否有区别。

this.setState({ name: xx }, () => this.setState({ age: 17 }))

vs

this.setState({ name: xx, age: 17 });

它们是完全相同的事物还是第一种方法实际上将确保首先更新name状态,并在更新状态age之前强制重新渲染

3 个答案:

答案 0 :(得分:1)

是的。嵌套状态很有意义。

嵌套状态更新可确保:

The state of first variable is updated.
The component is updated (re-rendered).
The state of second variable is updated.
The component is updated (re-rendered) again.

为了测试这一点,我在React项目中添加了以上两种情况。在此处查看仓库:

https://github.com/kramankishore/React-Nested-State

要测试组件是否正在重新渲染,我在shouldComponentUpdate()函数中添加了控制台日志。

组件更新按以下顺序进行:

static getDerivedStateFromProps()
shouldComponentUpdate()
render()
getSnapshotBeforeUpdate()
componentDidUpdate()

通常情况下,当您在浏览器中检查控制台日志时,您会看到“触发了渲染!”。仅被记录一次。但是在嵌套的情况下,您可以看到它被记录了两次,表明该组件被更新了两次。

以下是您要尝试的组件代码:

import React, { Component } from "react";

class NestedState extends Component {
  state = {
    var1: 0,
    var2: 0,
    var3: 0,
    var4: 0
  };

  incrementHandler = () => {
    this.setState({ var1: this.state.var1 + 1, var2: this.state.var2 + 1 });
  };

  incrementHandlerNested = () => {
    this.setState({ var3: this.state.var3 + 1 }, () =>
      this.setState({ var4: this.state.var4 + 1 })
    );
  };

  shouldComponentUpdate() {
    console.log("Rerender triggered!");
    return true;
  }

  render() {
    return (
      <div>
        <h1>Normal</h1>
        <a>{this.state.var1}</a>
        <a>{this.state.var2}</a>
        <div />
        <button onClick={this.incrementHandler}>Increment</button>
        <h1>Nested</h1>
        <a>{this.state.var3}</a>
        <a>{this.state.var4}</a>
        <div />
        <button onClick={this.incrementHandlerNested}>Increment</button>
      </div>
    );
  }
}

export default NestedState;

正常案例输出(在浏览器控制台中):

Rerender triggered!

嵌套案例输出(在浏览器控制台中):

Rerender triggered!
Rerender triggered!

希望这会有所帮助!

答案 1 :(得分:0)

this.setState({ name: xx }, () => this.setState({ age: 17 })) 

使用此方法,可以确保仅在名称设置为xx后将年龄设置为17。但是在后者中,它可以同时发生,也可以以setState异步的任何顺序发生。

答案 2 :(得分:0)

两种方法都可以,但是问题是为什么您需要它? 那将花费您新的翻译。当然,如果您不能避免这种情况。