ReactJS - 如何更新嵌套和“正常”状态属性?

时间:2018-06-17 15:22:20

标签: javascript reactjs state axios react-state-management

这就是state的样子:

constructor(props, context) {
    super(props, context);

    this.state = {
      show: false,
      btnLabel: 'GO!',
      car: {
        owner: false, 
        manufacturer: false, 
        color: false
      }
    };
  }

这就是我修改state的方式:

handleClickFetchPrice() {
      this.setState({btnLabel: 'Fetching data...' });
      console.log(this.state.fetchPriceBtn);

      const url = 'some url';
      axios.get(url)
        .then(res => {
          let car = [...this.state.car];
          car.owner = res.data.owner;
          car.manufacturer = res.data.manufacturer;
          car.color = res.data.color;
          this.setState({car});
        })
  }

属性car已更新,但fetchPriceBtn未更新 - console.log(this.state.fetchPriceBtn);的输出仍为GO!

我在俯瞰什么?为什么fetchPriceBtn没有更新?

3 个答案:

答案 0 :(得分:1)

React setState是一个异步过程 - 您不确切知道何时更新,您只能安排更新。

要实现所需的功能,您可以在setState方法中提供回调。

this.setState({ btnLabel: 'Fetching data...' }, () => console.log(this.state.fetchPriceBtn))

您可以在方法上了解更多following the documentation

答案 1 :(得分:1)

@christopher是对的,setState是一个异步过程。但是当第二次调用handleClickFetchPrice()函数时,btnLabel的值将等于Fetching data...

答案 2 :(得分:1)

如前面的答案中所述,setState是异步的,因此您的console.log无法立即赶上状态更改。再次按照建议您可以使用回调函数来跟踪此更改,但如果您仅使用console.log进行调试或想要查看状态中的哪些更改,则可以在渲染功能中执行此操作。使用回调只是为了调试不是一个好方法。它的目的在某种程度上是不同的,如果你查看官方文档,那么建议使用componentDidMount方法来实现这种逻辑。

render() {
    console.log( this.state.foo );
    return (...)
}

如果你这样做,你会看到两个console.log输出,一个在状态改变之前,一个在之后。

此外,您的州运营可能会得到加强。您的car属性不是数组,但是您将它转换为数组并进行设置?这是你想要的:

axios.get(url)
    .then(res => {
        const { owner, manufacturer, color } = res.data;
        this.setState( prevState => ( { car: { ...prevState.car, owner, manufacturer, color } } ) );
     })

这里我们不是直接改变我们的状态,而是使用扩展运算符并设置所需的属性。对于您的示例,我们实际上是设置整个属性。

最后一点,我想你想做那样的事情:

this.setState( { btnLabel: "fetching } );
axios.get(url)
    .then(res => {
        const { owner, manufacturer, color } = res.data;
        this.setState( prevState => ( { car: { ...prevState.car, owner, manufacturer, color }, btnLabel: "go" } ) );
     })

如果您的意图以某种方式进行状态更改/检查,这可能不是一个好的逻辑,因为您已经看到setState不是同步的。小心这样做。