By TheCoder


2019-04-15 10:31:10 8 Comments

I am having an update form to update the user's info.

 const { basic: userBasic } = this.state.user; 

 <Modal open={openEditBasicModal} size="small">
      <Modal.Header>Your basic details</Modal.Header>
      <Modal.Content scrolling>
        <Form>
          <Form.Group inline widths="equal">
            <Form.Input
              fluid
              type="text"
              name="firstName"
              defaultValue={userBasic.firstName}
              onChange={this.handleBasicFromInputValue}
              label="First Name"
            />
            <Form.Input
              fluid
              type="text"
              name="lastName"
              defaultValue={userBasic.lastName}
              onChange={this.handleBasicFromInputValue}
              label="Last Name"
            />
          </Form.Group>             
        </Form>
      </Modal.Content>
      <Modal.Actions open={true}>
        <Button
          primary
          onClick={this.updateUserBasicInfo}>
          Update
        </Button>
      </Modal.Actions>
    </Modal>

The component's state is:

this.state = {
      user: {
        basic: {
          firstName: null,
          lastName: null,
          email: null
        },
        //others
      }
}

The default value in the form is from the state and the logic is to update the state by using onChange handler on the forms fields. So I used the one simple handler for this:

handleBasicFromInputValue = event => {
    this.setState({
      user: {
        basic: {
          [event.target.name]: event.target.value
        }
      }
    });
  };

The above handler DID update the state, BUT it also remove the state schema declared in the component. If the user state was having

user: {
    basic: {
      firstName: "theCoder",
      lastName: "lastCoder",
      email: "[email protected]"
    }
}

and now I update the firstName field in the form, the state gets changed to

user: {
    basic: {
      firstName: "theCoderUpdated",
    }
}

If I print the user state now on form submit:

  updateUserBasicInfo = () => {
    console.log(this.state.user.basic);
  }

It only prints object containg firstName: "theCoderUpdated"

All other state variables have vanished. Shouldn't the other state variables remain unchanged?
I think this is the [event.target.name] which is causing the issue, but I am not sure why.

How does the [event.target.name] works behind the scene? And what would be the right way to do this state change?

5 comments

@fg93 2019-04-15 10:40:01

I think your problem is when you create the new state that you don't maintain the old values.

Try this:

    handleBasicFromInputValue = event => {
      const { user } = this.state;        
      this.setState({
          user: {
            ...user,
            basic: {
              ...user.basic,
              [event.target.name]: event.target.value
            }
          }
        });
      };

When you do "setState" you are creating a new state so that's when you change what you want but you must also maintain what you already had.

You can see that in React docs

With spread operator you are making a copy of what you already had and you add what you want to change.

PS: what you want to change always behind what you already had because otherwise it is possible to replace it since you are making a copy of what was before.

I hope I helped you :)

@Dblaze47 2019-04-15 10:45:31

You replace the state with the new one when assigning the firstName, as you are going beyond shallow copy. You have to do it like this:

handleBasicFromInputValue = (event) => {
   var temp = this.state.user;
   temp.basic[event.target.name] = event.target.value;
   this.setState({
      user: temp
   });
 };

@Raj 2019-04-15 10:43:14

You are replacing the basic object. you can do it like .

this.state.user.basic[event.target.name] =event.target.value; this.setState({user : this.state.user});

@Dblaze47 2019-04-15 10:47:10

It is a bad practice to directly work on an immutable state. What's the whole point of setState() here?

@pgsandstrom 2019-04-15 10:39:05

React only does shallow state merging. You can read about it here:

https://reactjs.org/docs/state-and-lifecycle.html#state-updates-are-merged

That means that all when you call setState, all the top level properties are replaced completetly. For you, that means that user is completely replaced with the new user-object that you send in with setState. You can solve this in two ways. Either you flatten your state object, and have firstName, lastName, email in your state like this:

this.state = {
  firstName: null,
  lastName: null,
  email: null
}

or you have to update your state like this:

handleBasicFromInputValue = event => {
    this.setState({
      user: {
        basic: {
          ...this.state.user.basic,
          [event.target.name]: event.target.value
        }
      }
    });
  };

@Murat Karagöz 2019-04-15 10:34:22

You are replacing the basic object. Do it like this to keep the previous props

const shallowCopy = Object.assign({}, this.state.user);
shallowCopy.basic[event.target.name] = event.target.value
this.setState({user : shallowCopy});

Related Questions

Sponsored Content

79 Answered Questions

[SOLVED] How do I remove a particular element from an array in JavaScript?

  • 2011-04-23 22:17:18
  • Walker
  • 5781437 View
  • 7209 Score
  • 79 Answer
  • Tags:   javascript arrays

35 Answered Questions

[SOLVED] How do I return the response from an asynchronous call?

54 Answered Questions

[SOLVED] How do I check if an element is hidden in jQuery?

38 Answered Questions

[SOLVED] How do I remove a property from a JavaScript object?

55 Answered Questions

[SOLVED] How do I include a JavaScript file in another JavaScript file?

86 Answered Questions

[SOLVED] How do JavaScript closures work?

58 Answered Questions

[SOLVED] How do I redirect to another webpage?

26 Answered Questions

[SOLVED] What does "use strict" do in JavaScript, and what is the reasoning behind it?

28 Answered Questions

[SOLVED] How to change an element's class with JavaScript?

  • 2008-10-12 20:06:43
  • Nathan Smith
  • 2365008 View
  • 2543 Score
  • 28 Answer
  • Tags:   javascript html dom

6 Answered Questions

[SOLVED] Why does Google prepend while(1); to their JSON responses?

Sponsored Content