setState在map函数中的反应

时间:2018-06-04 06:10:41

标签: reactjs react-redux react-state-management

我的要求是更新componentWillReceiveProps的map函数中的状态值。

在控制台日志中,我得到的是1s但sub.subscribed包含0和1

控制台窗口参考:http://prntscr.com/jqifiz

constructor(props) {
    super(props);
      this.state = {
        regionAll: [],
      };
    }
componentWillReceiveProps(nextProps){
    if(nextProps.apiData !== false ){
      nextProps.apiData.data.datacenter.category.map((sub)=> {
        console.log(sub.subscribed,'sub.subscribed');
        this.setState({
          regionAll: [
            ...this.state.regionAll,
            sub.subscribed
          ]
        },()=>{
          console.log(this.state.regionAll,'sub');
        })
      })
  }

这是在reactjs中更新状态的正确方法吗?

2 个答案:

答案 0 :(得分:1)

setState是async.In Array#map,它调用了多次。只有最后一个值被添加到数组regionAll而不是全部,因为异步setState调用具有多个值。

您可以使用Array#reducer收集单个数组中的所有sub.subscribed值,然后执行状态更新。

if (nextProps.apiData !== false) {

    let sub = nextProps
        .apiData
        .data
        .datacenter
        .category
        .reduce((accum, sub) => [
            ...accum,
            sub.subscribed
        ], [])

    this.setState({
        regionAll: [...sub]
    }, () => {
        console.log(this.state.regionAll, 'sub');
    })
}

答案 1 :(得分:0)

问题出现是因为setState调用是批处理的,并且您更新了基于prevState的React状态,您应该在这种情况下使用函数状态

componentWillReceiveProps(nextProps){
    if(nextProps.apiData !== false ){
      nextProps.apiData.data.datacenter.category.map((sub)=> {
        console.log(sub.subscribed,'sub.subscribed');
        this.setState(prevState => ({
          regionAll: [
            ...prevState.regionAll,
            sub.subscribed
          ]
        }),()=>{
          console.log(this.state.regionAll,'sub');
        })
      })
  }

然而,在地图中调用setState是一个坏主意,你可以改为从map获取数据并调用setState只需一次

componentWillReceiveProps(nextProps){
    if(nextProps.apiData !== false ){
      const subscribed = nextProps.apiData.data.datacenter.category.map((sub)=> {
        console.log(sub.subscribed,'sub.subscribed');
        return sub.subscribed;
      })
      this.setState(prevState => ({
          regionAll: [
            ...this.state.regionAll,
            ...subscribed
          ]
        }),()=>{
          console.log(this.state.regionAll,'sub');
     })
  }