Save array of objects in state - ReactJS
Solution 1
Instrument is an object, and you are trying to render it, use the specific value that you wants to render, Try this:
musicListenChange(val){
let user = this.state.user;
user['music_listen'] = val.value;
this.setState({user: user);
}
saveInstrument(){
let user = this.state.user;
user['instruments'] = user['instruments'] ? user['instruments'] : [];
user['instruments'].push(this.state.instruments);
this.setState({user: user});
}
In render function use this:
{this.state.user.instruments ?
this.state.user.instruments.map((instrument, index) => {
return (<button className="btn btn-default">{instrument.name}</button>)
})
:<div/>
}
Solution 2
The problem is here:
<div className="container-tags">
{this.state.user.instruments ? this.state.user.instruments.map(function (instrument, index) {
return <button className="btn btn-default">{instrument}</button>;
}) : <div></div>}
</div>
When realising that instrument
is a JavaScript object (you said that your instruments
array contains objects with structure {name: "string", experience:"string"}
), the error message becomes clear: you are trying to insert an object as a child of the <button>
element, which is not allowed, since React has no idea how to display an object. If you used instrument.name
or instrument.experience
instead (which are strings), your code will work.
The Condor
Updated on March 02, 2020Comments
-
The Condor about 4 years
I am building a ReactJS application, and I need to store data in this way:
this.state = { user: { name: "", surname: "", age: "", ... instruments: [], } }
The
instruments
state needs to contain several objects, with propertiesname
andexperience
. An example:instruments: [ { name: 'Bass guitar', experience: 7, }, { name: 'Drums', experience: 1, } ... ]
I'm new to React, so far I have been able to save data in similar arrays by doing this:
musicListenChange(val){ let musicListenArray = this.state.user.music_listen ? this.state.user.music_listen : []; musicListenArray.push(val.value); this.setState({user: {...this.state.user, music_listen: musicListenArray}}); }
However, when I try to save an object with the following code I receive an error:
saveInstrument(){ // save current instruments state in array, or create an empty one let array = this.state.user.instruments ? this.state.user.instruments : []; // in this.state.instruments I saved a temporary copy of the selected instrument, put it in the array array.push(this.state.instruments); this.setState({user: {...this.state.user, instruments: array }}); console.log('instrum. state: ', this.state.user.instruments); }
Error code
Uncaught Error: Objects are not valid as a React child (found: object with keys {name, experience}). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons. Check the render method of `EditProfile`.
My EditProfile render part for the instruments
<div className="container-tags"> {this.state.user.instruments ? this.state.user.instruments.map(function (instrument, index) { return <button className="btn btn-default">{instrument}</button>; }) : <div></div>} </div>
Any idea on how to fix this? Thanks
-
The Condor over 7 yearsthis.state.instruments is not an array actually, it's an object. So I think the problem is not there.. but thanks for trying
-
Mayank Shukla over 7 yearsif this.state.instrument is an object then how u r using {instrument} in html, how you are printing an object.
-
Mayank Shukla over 7 yearsi did some changes, plz check.
-
p4sh4 over 7 years@TheCondor You must be confused,
this.state.instruments
is definitely an array since you define it likeinstruments: []
and then do array operations on it, such aspush
ormap
. It's an array of objects. -
The Condor over 7 yearsPerfect, this was the problem! But the other user replied before and suggested the same solution, therefore I gave the right answer to him. Thanks!
-
tonix almost 5 yearsI would say that this is considered a bad practice. A new object for
user
must be recreated each time state changes withsetState()
, e.g.const user = { ...this.state.user }
before changinguser
, then you can make changes touser
and finally callsetState({user})
. This way you allow your state to work with pure components too, otherwise they won't rerender.