简体   繁体   English

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

[英]ReactJS - how do I update nested and “normal” state properties?

This is how my state looks like: 这是我的state

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

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

and this is how I modify state : 这就是我修改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});
        })
  }

The attribute car is updated, but fetchPriceBtn is not - the output of console.log(this.state.fetchPriceBtn); 属性car已更新,但fetchPriceBtn不是fetchPriceBtn console.log(this.state.fetchPriceBtn);的输出console.log(this.state.fetchPriceBtn); is still GO! 还是GO! .

What am I overlooking? 我在俯视什么? Why the fetchPriceBtn is not updated? 为什么fetchPriceBtn没有更新?

React setState is an asynchronous process - you don't know exactly when it will be updated, you can only schedule the update. React setState是一个异步过程-您不知道何时更新它,只能安排更新。

To achieve your desired functionality, you can provide a callback into the setState method. 为了实现所需的功能,可以向setState方法提供回调。

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

You can learn more following the documentation on the method. 您可以按照该方法的文档了解更多信息。

@christopher is right, setState is an asynchronous process. @christopher是正确的, setState是一个异步过程。 But when second time call handleClickFetchPrice() function your btnLabel is value will be equal to Fetching data... 但是当第二次调用handleClickFetchPrice()函数时,您的btnLabel值等于Fetching data...

As answered in previous answers setState is asynchronous, so your console.log can't catch up the state change immediately. 正如先前答案中回答的那样,setState是异步的,因此您的console.log无法立即赶上状态更改。 Again as suggested you can use callback function to track this change but if you use console.log just for debugging or want to see what changes in your state you can do this in your render function. 再次建议,您可以使用回调函数来跟踪此更改,但是,如果仅将console.log用于调试或想查看状态的更改,则可以在渲染函数中执行此操作。 And using a callback just for debug is not a nice way. 而且仅将回调用于调试不是一个好方法。 Its purpose somehow different and if you check the official documentation, componentDidMount method is being suggested for such logic. 它的用途有所不同,如果您查看官方文档,则建议将componentDidMount方法用于这种逻辑。

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

If you do that you see two console.log output, one before state change and one after. 如果这样做,您会看到两个console.log输出,一个在状态更改之前,另一个在状态更改之后。

Also, your state operations might be enhanced. 此外,您的状态操作可能会得到增强。 You car property is not an array, but you are converting it to an array and setting it? 您的汽车属性不是数组,但是您要将其转换为数组并进行设置? Is this what you intend: 这是您打算的吗?

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

Here we are not mutating our state directly, instead we are using spread operator and setting the desired properties. 这里我们不是直接改变状态,而是使用散布运算符并设置所需的属性。 For your example we are setting the whole property actually. 对于您的示例,我们实际上是在设置整个属性。

One last note, I think you want to do that something like that: 最后一点,我想您想这样做:

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

If your intention is somehow to do a status change/check this might no be a good logic as you have seen setState is not synchronous. 如果您打算以某种方式进行状态更改/检查,那么这可能不是一个好的逻辑,因为您已经看到setState不同步。 Do this carefully. 仔细做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM