2

I am tring to update a single value in the state, this is my state:

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: ''
      }
    ]
  };

I got the value I want to update and the index of the object inside the array but I cant find a way to update the value... This is what I have so far:

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

as well I thought tried this block

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

any help would be amazing tnx!

4 Answers 4

4

Ideally you should use this

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)
})
Sign up to request clarification or add additional context in comments.

1 Comment

There was an edit issue. On bus, answering from phone 🙈 hope you understand.
4

When you're working with React state, you're working with an immutable data structure Immutable.js can be a lifesaver.

But we can also do it without dependencies with map and object spread:

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

5 Comments

You shouldn't use the state directly to map it either. Bad practice.
@SubhenduKundu it's actually correct to do it this way. The map function on an array creates a new array, therefore this is so far the only non-mutating solution, albeit a bit hard to follow for newer developers :)
@SubhenduKundu yup preferably you can also use the form of setState that receives a function instead of an update object, but I think it's only required for the rare occasion of possible race condition -- such as when toggling things
it's not "required" per se, but you are correct in that the biggest benefit of passing a function to set state is that your calls to setState will happen synchronously reactjs.org/docs/…
Yup you are right, however your might wanna look at codereview.stackexchange.com/questions/160411/… also there few articles on this why you shouldn't use the state.map directly. I will update you once I get a hold of my laptop.
1

Generally when working with state you want to perform only pure operations, because mutating state can lead to confusing, difficult to locate bugs.

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

This can get pretty cumbersome, but it is core to the philosophy of React itself. If you wanna make it easier on yourself, I recommend checking out immer, an NPM library that exports one function, produce. I don't normally recommend third party libraries as solutions, but I particularly love immer. It will look weird at first, but it works by using something called a Proxy (a new language feature in ES6):

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

Often immer is not needed, but when working with arrays of objects and especially with nested object structures it can be a godsend in helping you write clean code that works well.

Comments

0

you cant change const variables,

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

if you have the value and the index of your data in array just do it

let state = {...this.state}

state.courses[INDEX].courseGrade = courseGrade;

this.setState({...state})

i hope it useful

3 Comments

Why would this work? Please explain what the issue was and why changing to this will work
Good start to the solution! But be careful that this is a mutating change and should be avoided if possible.
you definitely can change them, the only thing const prevents is reassignment. It's also worth nothing that the spread operation only shallow clones, so the courses array and each individual course are still passed by reference and being mutated here. It would be better to use this.state.slice()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.