React中使用map方法设置数组对象的setState不起作用?

7

我遇到了一个问题,无法通过setState改变嵌套数组对象中的值。下面的代码本应将id为2的问题更改为答案:true,但它没有实现,出了什么问题?

this.state = {
  questions: [
    {
      id: 1,
      answer: ''
    },
    {
      id: 2,
      answer: ''
    },
  ]
}
//I have a click event somewhere
this.setState(
  {
    questions: this.state.questions.map(q => {
      if (q.id === 2) {
        return {
          ...q,
          answer: true
        }
      } else {
        return { ...q }
      }
    })
  },
  console.log(this.state.questions[1]) // did not see id of 2 being changed to true?
)

@Finesse 这是状态,已更新 - Alisa T Morgan
实际上,OP 正确地更新了状态。 - devserkan
3个回答

4

console.log(this.state.questions[1])这行代码在this.setState语句之前被执行,那就是为什么旧的状态会被打印到控制台上。您应该将该行代码放入一个函数中以延迟执行:

this.setState(..., () => console.log(this.state.questions[1]));

如果改变的状态是从当前状态派生出来的,建议使用函数作为第一个参数,因为React不会立即应用新状态,因此this.state在React应用新状态时可能已经过时:

this.setState(state => ({
  questions: state.questions.map(q => {
    if (q.id === 2) {
      return {...q, answer: true};
    }
    return q;
  })
}), () => {
  console.log(this.state.questions[1]);
});

1
可能这里缺少了一部分 :) questions.map 应该是 state.questions.map。对吧? :) - devserkan

0

你没有调用你的 setState 回调函数。尝试像这样:

this.setState(
  {
    questions: this.state.questions.map(q => {
      if (q.id === 2) {
        return {
          ...q,
          answer: true
        };
      }
      return { ...q };
    })
  },
  () => console.log(this.state.questions[1]) // did not see id of 2 being changed to true?
);

虽然你正在使用当前状态来再次更新你的状态,但最好使用函数式setState。

this.setState(
  currentState => ({
    questions: currentState.questions.map(q => {
      if (q.id === 2) {
        return {
          ...q,
          answer: true
        };
      }
      return { ...q };
    })
  }),
  () => console.log(this.state.questions[1])
);

此外,您不必在回调函数中记录状态以使用 setState。您可以在 render 方法中记录状态,而无需使用 setState 的回调函数。
this.setState(
  currentState => ({
    questions: currentState.questions.map(q => {
      if (q.id === 2) {
        return {
          ...q,
          answer: true
        };
      }
      return { ...q };
    })
  })
);

....

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

-1

我认为这是因为Array.map返回一个数组。请尝试:

this.setState(
  {
    questions: this.state.questions.map(q => {
      if (q.id === 2) {
        q.answer = true;
      } 
      return q;
    })
  },
  console.log(this.state.questions[1]) // did not see id of 2 being changed to true?
)

3
嗨,@Charlie。作为关键建议,不要使用React、Redux等来改变你的状态或对象属性。永远不要这样做。OP做得很对。 - devserkan
没错,对象的不可变性就是Redux的原则。 - Charlie
另外,在React的状态中 :) 祝你在开发之旅中好运。 - devserkan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接