3

What would be the best way to change the state of multiple nested arrays of objects in React? Let's see the example below: I have a component that will display the top playlist for each genre. I have a property genre which is an array of objects and each object has a property songs which is also an array of objects. If I want to change the song named Soldier of Fortune to Child in Time (Let's suppose in Change function as parameters I have indexes of Song and Genre already provided from the UI change). How can I access multiple levels of nested objects and not mutate the state?

this.state = {
    title: 'Top playlists',
    genres: [
      {
        genreName: 'pop',
        followers: 2456,
        songs: [
          {
            title: 'Soldier of fortune',
            author: 'Deep Purple',
          },
        ],
      },
    ],
  };

handleChangeSongName = (e, genreIndex, songIndex) => {
    // genreIndex = 0;
    // songIndex = 0;
    // e.target.name = title;
    // e.target.value = "Child in time"  
    ...What to do here?
  }

2
  • This may be vague, but how about instead of using map ( I assumed u used map :D ) use a for loop or a while in which you can store the index of you'r array's as a component propriety ? Commented May 29, 2019 at 23:43
  • I am just curious about updating the state, not displaying the data. Let's suppose I have displayed everything and I have an input field where you have the list of the data and I got the correct index of song and index of the genre. I just need to figure out how to properly change the state Commented May 29, 2019 at 23:50

2 Answers 2

4

you can modify your handleChangeSongName function to this:

  handleChangeSongName = (e, genreIndex, songIndex) => {
// genreIndex = 0;
// songIndex = 0;
// e.target.name = title;
// e.target.value = "Child in time"  
this.setState((prevState) => {
  let temp = {
    ...prevState,
    genres: [...prevState.genres]
  }

  // change title "Soldier of fortune" to "Child in time"
  temp.genres[genreIndex].songs[songIndex][e.target.name] = e.target.value

  return temp
})

}

Sign up to request clarification or add additional context in comments.

7 Comments

This kinda works, but I am losing Focus after I type a single letter in the input field. So, I need to click again and type one more letter, and so on
It is a good practice to update those changes on button press. not when changing value on textInput. do a separate handling of your textInput.
Also can I know what component did you use for the input and how you implemented it?
I used Input from the 'reactstrap' module. I am mapping the array of the elements and then onChange, I am sending an event, what genre is and what song I am changing. Something like this. <Input value={songs[songIndex].title} onChange={(e) => {handleChange(e, genreIndex, songIndex, )}} />
Mine is working on simple TextInput component of react-native.I think you implement it right , but i dont know the cause of sudden unfocus while you triggering a key. But in my answer on your main question. that is one of the best way to change to state of a nested objects.
|
0

I would change your state like this:

this.state = {
      title: "Top playlists",
      genres: [
        {
          followers: 2456,
          genreName: "pop",
          songs: [
            {
              title: "Soldier of fortune",
              author: "Deep Purple"
            }
          ]
        }
      ]
    };

and then

handleChangeSongName = (e, genreIndex, songIndex) => {
    // genreIndex = 0;
    // songIndex = 0;
    // e.target.name = title;
    // e.target.value = "Child in time"  
    ...What to do here?

    const genres = _.cloneDeep(this.state.genres); // create deep copy with underscore
    // or like this
    // const genres = JSON.parse(JSON.stringify(this.state.genres))

    if(genres.length && genres[genreIndex] && genres[genreIndex].songs.length && genres[genreIndex].songs[songIndex]) {
        genres[genreIndex].songs[songIndex][e.target.name] = e.target.value;

        this.setState({
            genres: genres
        });
     }

  }

2 Comments

I think this will mutate the state cause I am directly working on its values?
Yes, you are right. You should create a deep copy of genres, and than manipulating before set a new state. I updated the answer.

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.