Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React - State Update value only of Particular key

I'm trying to experiment with React, I have a issue of updating state values of a particular key.

Here is my state

this.state = {
        connections : {
            facebook : "http://facebook.com",
            flickr : null,
            foursquare : null,
            googleplus : null,
            id : 0,
            instagram : "http://instagram.com/",
            openstreetmap : null,
            pinterest : null,
            place_id : 1,
            tomtom : null,
            tripadvisor : null,
            twitter : "http://twitter.com",
            vimeo : null,
            wikipedia : null,
            yelp : null,
            youtube : null
        },
        contact : {

        }
    }

I'm calling a external component and sending parameters to it.

<Connection type="Facebook" icon={facebookIcon} placeholder="Add Facebook Link" name="facebook" value={this.state.connections.facebook} onChange={this.handleChange.bind(this)}/>
<Connection type="Twitter" icon={twitterIcon} placeholder="Add Twitter Link" name="twitter" value={this.state.connections.twitter} onChange={this.handleChange.bind(this)}/>
<Connection type="Instagram" icon={instagramIcon} placeholder="Add Instagram Link" name="instagram" value={this.state.connections.instagram} onChange={this.handleChange.bind(this)}/>

Component in external file:

<input type="text" name={this.props.name} placeholder={this.state.placeholder} value={this.props.value} onChange={this.props.onChange} />

On change of value in textbox,

handleChange(e) {        
    this.setState({
        connections : {[e.target.name]: e.target.value}
    })
}

While I try to change any field values, it sets the rest 2 with empty. For example, if I try to edit textbox of Facebook, it sets Twitter and Instagram values to empty.

May I know what I'm doing wrong in setting handleChange? I'm sure its something wrong with this.setState, but not sure how to target particular key value.

like image 982
Deepak Bandi Avatar asked Dec 30 '16 20:12

Deepak Bandi


People also ask

How do we update a component single state object?

Give it a value. Create another method inside the class and update the state of the component using 'this. setState()' method. Pass the state object in a JSX element and call the method to update the state on a specific event like button click.

How do I change my value in state React?

state , we use this. setState() . This is a function available to all React components that use state, and allows us to let React know that the component state has changed. This way the component knows it should re-render, because its state has changed and its UI will most likely also change.

Why we should not directly update state in React?

React will then look at the virtual DOM, it also has a copy of the old virtual DOM, that is why we shouldn't update the state directly, so we can have two different object references in memory, we have the old virtual DOM as well as the new virtual DOM.

Can we directly modify state in React?

In React, the state is immutable. In simple terms it means that you should not modify it directly.


2 Answers

You should actually rather use

handleChange(e) {
  this.setState(oldState => ({
    connections: {[e.target.name]: e.target.value, ...oldState.connections},
  }));
}

because otherwise you might overwrite state-changes that have not been applied yet.

see https://reactjs.org/docs/state-and-lifecycle.html

like image 136
Wuwala Wala Avatar answered Oct 06 '22 00:10

Wuwala Wala


setState performs a shallow merge instead of a deep one (more explanation in the docs), so you're completely overwriting all of connections with just your one value. If you want to keep the other keys in connections intact, you can change handleChange to this:

handleChange(e) {        
    this.setState({
        connections : {...this.state.connections, [e.target.name]: e.target.value}
    })
}

This will shallow copy all of this.state.connections, and then set e.target.name over top of it.

like image 25
Drew Schuster Avatar answered Oct 06 '22 00:10

Drew Schuster