DEV Community

Abu Jaid
Abu Jaid

Posted on

How to update nested state in react component without using redux

In this article, I'm going to create a simple registration form using bootstrap where we will make a functional component, in this component we will use react useState() hooks,where will make a nested state in a single object and try to update the nested object.it is very difficult to update nested state in real life project.
I'm hoping you are familiar with basic of reactjs,we are not going the basic settings of reactjs,we are going to jump on registration form creation.

let's start to create registration form using Bootstraps.
in App.js file we will create registration form
just copy the snippet of html code.

 <div>
      <form onSubmit={submit}>
        <div className="form-group">
          <input
            type="text"
            className="form-control"
            placeholder="Username"
            name="username"
          />
        </div>
        <div className="form-group">
          <input
            type="text"
            className="form-control"
            placeholder="Email"
            name="email"
          />
        </div>
        <div className="form-group">
          <input
            type="text"
            className="form-control"
            placeholder="State"
            name="state"
          />
        </div>
        <div className="form-group">
          <input
            type="text"
            className="form-control"
            placeholder="City"
            name="city"
          />
        </div>
        <div className="form-group">
          <input
            type="text"
            className="form-control"
            placeholder="Latitude"
            name="lat"
          />
        </div>
        <div className="form-group">
          <input
            type="text"
            className="form-control"
            placeholder="Longitude"
            name="long"
          />
        </div>
        <div className="form-group">
          <button type="submit" className="btn btn-primary">
            Submit
          </button>
        </div>
      </form>
    </div>
Enter fullscreen mode Exit fullscreen mode

now let's start to create a state where the user data will be available in our component.
App.js

export default function App() {
  const [user, setUser] = React.useState({
    username: '',
    email: '',
    address: {
      state: '',
      city: '',
      geolocation: {
        lat: '',
        long: ''
      }
    }
  });

  }
Enter fullscreen mode Exit fullscreen mode

Here we have created a state with nestes state.now lets add name and value attributes in our html code and also add a form submit method submit and onChange event onChange into html inputs field.

 <div>
      <form onSubmit={submit}>
        <div className="form-group">
          <input
            type="text"
            className="form-control"
            placeholder="Username"
            name="username"
            value={user.username}
            onChange={onChange}
          />
        </div>
        <div className="form-group">
          <input
            type="text"
            className="form-control"
            placeholder="Email"
            name="email"
            onChange={onChange}
          />
        </div>
        <div className="form-group">
          <input
            type="text"
            className="form-control"
            placeholder="State"
            name="state"
            value={user.address.state}
            onChange={onChange}
          />
        </div>
        <div className="form-group">
          <input
            type="text"
            className="form-control"
            placeholder="City"
            name="city"
            value={user.address.city}
            onChange={onChange}
          />
        </div>
        <div className="form-group">
          <input
            type="text"
            className="form-control"
            placeholder="Latitude"
            name="lat"
            value={user.address.geolocation.lat}
            onChange={onChange}
          />
        </div>
        <div className="form-group">
          <input
            type="text"
            className="form-control"
            placeholder="Longitude"
            name="long"
            value={user.address.geolocation.long}
            onChange={onChange}
          />
        </div>
        <div className="form-group">
          <button type="submit" className="btn btn-primary">
            Submit
          </button>
        </div>
      </form>
    </div>
Enter fullscreen mode Exit fullscreen mode

onChange events

const onChange = e => {
    let data = { ...user };
    let name = e.target.name;
    let val = e.target.value;
    if (name == 'username' || name == 'email') {
      data = { ...data, [name]: val };
    } else if (name == 'state' || name == 'city') {
      data = {
        ...data,
        address: {
          ...data.address,
          [name]: val
        }
      };
    } else if (name == 'lat' || name == 'long') {
      data = {
        ...data,
        address: {
          ...data.address,
          geolocation: {
            ...data.address.geolocation,
            [name]: val
          }
        }
      };
    }
    setUser(data);
  };
Enter fullscreen mode Exit fullscreen mode

and onSubmit event submit

const submit = e => {
    e.preventDefault();
    console.log(user);
  };
Enter fullscreen mode Exit fullscreen mode

let's see the whole code together.
App.js

import React from 'react';
export default function App() {
  const [user, setUser] = React.useState({
    username: '',
    email: '',
    address: {
      state: '',
      city: '',
      geolocation: {
        lat: '',
        long: ''
      }
    }
  });
  const onChange = e => {
    let data = { ...user };
    let name = e.target.name;
    let val = e.target.value;
    if (name == 'username' || name == 'email') {
      data = { ...data, [name]: val };
    } else if (name == 'state' || name == 'city') {
      data = {
        ...data,
        address: {
          ...data.address,
          [name]: val
        }
      };
    } else if (name == 'lat' || name == 'long') {
      data = {
        ...data,
        address: {
          ...data.address,
          geolocation: {
            ...data.address.geolocation,
            [name]: val
          }
        }
      };
    }
    setUser(data);
  };
  const submit = e => {
    e.preventDefault();
    console.log(JSON.stringify(user));
  };
  return (
    <div>
      <form action="">
        <div className="form-group">
          <input
            type="text"
            className="form-control"
            placeholder="Username"
            name="username"
            value={user.username}
            onChange={onChange}
          />
        </div>
        <div className="form-group">
          <input
            type="text"
            className="form-control"
            placeholder="Email"
            value={user.email}
            name="email"
            onChange={onChange}
          />
        </div>
        <div className="form-group">
          <input
            type="text"
            className="form-control"
            placeholder="State"
            name="state"
            value={user.address.state}
            onChange={onChange}
          />
        </div>
        <div className="form-group">
          <input
            type="text"
            className="form-control"
            placeholder="City"
            name="city"
            value={user.address.city}
            onChange={onChange}
          />
        </div>
        <div className="form-group">
          <input
            type="text"
            className="form-control"
            placeholder="Latitude"
            value={user.address.geolocation.lat}
            name="lat"
            onChange={onChange}
          />
        </div>
        <div className="form-group">
          <input
            type="text"
            className="form-control"
            placeholder="Longitude"
            value={user.address.geolocation.long}
            name="long"
            onChange={onChange}
          />
        </div>
        <div className="form-group">
          <button className="btn btn-primary" onClick={submit}>
            Submit
          </button>
        </div>
      </form>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Top comments (2)

Collapse
 
swagwik profile image
Sattwik Sahu

That's the exact reason why we use immer with Redux / other state management libraries. The process of updating the nested state involves so many ...s and nested arrays, objects which are not required after using immer.

Maybe you could include it in the post, showing a solution to this problem of unnecessarily long code.

Collapse
 
abu profile image
Abu Jaid

Thanks @sattwik sahu