【问题标题】:React, update single value in state made of array of objects反应,更新由对象数组组成的状态中的单个值
【发布时间】:2019-07-25 20:59:01
【问题描述】:

我正在尝试更新状态中的单个值, 这是我的状态:

state = {
    courses: [
      {
        id: 1,
        courseName: 'lenguage',
        courseType: false,
        courseHours: 10,
        courseGrade: ''
      },{
        id: 2,
        courseName: 'Math',
        courseType: true,
        courseHours: 20,
        courseGrade: ''
      },{
        id: 3,
        courseName: 'Biology',
        courseType: false,
        courseHours: 30,
        courseGrade: ''
      }
    ]
  };

我得到了要更新的值和数组内对象的索引,但我找不到更新值的方法... 这是我目前所拥有的:

  updateCourseGrade(courseGrade, id){
        const index = this.state.courses.findIndex(course => (
          id === course.id
        ));



    const courses = [...this.state.courses];
    courses[index].courseGrade = courseGrade;
    this.setState({courses});
  }

我也想试试这个块

const course = this.state.courses[index];
this.setState({
  courses: [...this.state.courses, course.courseGrade: courseGrade]
})

任何帮助都会很棒 tnx!

【问题讨论】:

    标签: reactjs state


    【解决方案1】:

    你不能改变 const 变量,

    const courses = [...this.state.courses];
        courses[index].courseGrade = courseGrade;
        this.setState({courses});
    

    如果您有数组中数据的值和索引,请执行此操作

    let state = {...this.state}
    
    state.courses[INDEX].courseGrade = courseGrade;
    
    this.setState({...state})
    

    希望对你有用

    【讨论】:

    • 为什么会这样?请解释问题是什么以及为什么改成这个会起作用
    • 解决方案的良好开端!但请注意,这是一个变异更改,应尽可能避免。
    • 您绝对可以更改它们,const 唯一阻止的是重新分配。传播操作只是浅层克隆也毫无价值,因此课程数组和每个单独的课程仍然通过引用传递并在此处进行变异。最好使用this.state.slice()
    【解决方案2】:

    当您使用 React 状态时,您正在使用不可变数据结构 Immutable.js 可以成为救星。

    但我们也可以在不依赖 map 和 object spread 的情况下做到这一点:

    this.setState({
        courses: this.state.courses.map(course => course.id === id ? { ...course, courseGrade } : course)
    })
    

    【讨论】:

    • 您也不应该直接使用状态来映射它。不好的做法。
    • @SubhenduKundu 这样做实际上是正确的。数组上的 map 函数创建了一个新数组,因此这是迄今为止唯一的非变异解决方案,尽管对于新开发人员来说有点难以理解:)
    • @SubhenduKundu yup 最好你也可以使用setState 的形式来接收一个函数而不是一个更新对象,但我认为它只是在极少数可能出现竞争条件的情况下才需要 - 例如切换时
    • 它本身不是“必需的”,但您是正确的,将函数传递给设置状态的最大好处是您对 setState 的调用将同步发生reactjs.org/docs/…
    • 是的,你是对的,但是你可能想看看codereview.stackexchange.com/questions/160411/… 也有一些关于为什么你不应该直接使用 state.map 的文章。一旦我拿到我的笔记本电脑,我会更新你。
    【解决方案3】:

    理想情况下你应该使用这个

    this.setState((prevState) => {
    // Use prevState and do the map just like someone suggested in one of the answer
     courses: prevState.map(course => course.id === id ? {...course, courseGrade } : course)
    })
    

    【讨论】:

    • 存在编辑问题。公交车上,电话接听?希望大家理解。
    【解决方案4】:

    通常在使用状态时,您只想执行纯操作,因为变异状态会导致混乱,难以定位错误。

    updateCourseGrade = (courseGrade, id) => {
      const course = this.state.courses.find(course => course.id === id);
      if (course) {
        const updatedCourse = { ...course, courseGrade };
        const updatedCourses = this.state.courses
          .filter(course => course.id !== id)
          .concat(updatedCourse);
        this.setState({ courses: updatedCourses });
      }
    }
    

    这可能会变得很麻烦,但它是 React 本身哲学的核心。如果你想让自己更轻松,我建议查看immer,这是一个导出一个函数的 NPM 库,produce。我通常不推荐第三方库作为解决方案,但我特别喜欢 immer。一开始它看起来很奇怪,但它通过使用称为 Proxy(ES6 中的新语言特性)的东西来工作:

    updateCourseGrade = (courseGrade, id) => {
      this.setState((
        produce(draftState => {
          const index = draftState.courses.findIndex(course => (
            id === course.id
          ));
          draftState.courses[index].courseGrade = courseGrade;
        })
      ))
    }
    

    通常不需要 immer,但在处理对象数组时,尤其是嵌套对象结构时,它可以帮助您编写运行良好的干净代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-08
      • 1970-01-01
      • 2021-12-26
      • 2015-11-21
      • 2018-09-18
      • 2018-11-09
      • 2021-12-23
      相关资源
      最近更新 更多