4

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 properties name and experience. 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

2
  • what do you have inside this.state.instruments? Commented Dec 10, 2016 at 11:37
  • Inside this.state.instruments I save {name: "string", experience:"string"} Commented Dec 10, 2016 at 11:57

2 Answers 2

5

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

5 Comments

this.state.instruments is not an array actually, it's an object. So I think the problem is not there.. but thanks for trying
if this.state.instrument is an object then how u r using {instrument} in html, how you are printing an object.
i did some changes, plz check.
@TheCondor You must be confused, this.state.instruments is definitely an array since you define it like instruments: [] and then do array operations on it, such as push or map. It's an array of objects.
I would say that this is considered a bad practice. A new object for user must be recreated each time state changes with setState(), e.g. const user = { ...this.state.user } before changing user, then you can make changes to user and finally call setState({user}). This way you allow your state to work with pure components too, otherwise they won't rerender.
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.

1 Comment

Perfect, this was the problem! But the other user replied before and suggested the same solution, therefore I gave the right answer to him. Thanks!

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.