Home > Software design >  React useState(), Why can't we update the previous value object and return it directly
React useState(), Why can't we update the previous value object and return it directly

Time:10-16

I tried the following code but it did not work and I don't really understand the reason for it. Wanted to display the first name, last name and email. But with the following code it does not render.

// prevValue[name] = value;
// return prevValue;

I know the better option is using spread method. but just wondering why doesn't it render up?

Expected outcome:

Expected outcome

import React, {
  useState
} from "react";

function App() {
  const [contact, setContact] = useState({
    fName: "",
    lName: "",
    email: ""
  });

  function handleContact(event) {
    const {
      value,
      name
    } = event.target;

    setContact((prevValue) => {
      // prevValue[name] = value;
      // return prevValue;

      /*Logged result
      {fName: "a", lName: "", email: ""}
      {fName: "s", lName: "", email: ""}
      {fName: "d", lName: "", email: ""}*/

      if (name === "fName") {
        return {
          fName: value,
          lName: prevValue.lName,
          email: prevValue.email
        };
      }
    });
    /*Logged result
    {fName: "", lName: "", email: ""}
    {fName: "a", lName: "", email: ""}
    {fName: "as", lName: "", email: ""}*/
    console.log(contact);
  }

  return ( <
    div className = "container" >
    <
    h1 >
    Hello {
      contact.fName
    } {
      contact.lName
    } <
    /h1> <
    p > {
      contact.email
    } < /p> <
    form >
    <
    input name = "fName"
    placeholder = "First Name"
    value = {
      contact.fName
    }
    onChange = {
      handleContact
    }
    /> <
    input name = "lName"
    placeholder = "Last Name"
    value = {
      contact.lName
    }
    onChange = {
      handleContact
    }
    /> <
    input name = "email"
    placeholder = "Email"
    value = {
      contact.email
    }
    onChange = {
      handleContact
    }
    /> <
    button > Submit < /button> <
    /form> <
    /div>
  );
}

export default App;

CodePudding user response:

When you call setContact, You get the previous value of state as an argument

And you have the option to use the previous value of state to return the new desired value of state contact

For setting the firstName, You can do something like this

setContact(prev => {...contact, firstName: value})

So the onChange handler for the <input /> can be

const handleFirstNameChange = () => {
   setContact(prev => {...contact, firstName: value})
}

But you dont want to write three such handlers for firstName, lastName and emailAddress just to update your contact state variable

So you can write a single wrapper function like

const handleContactChange = (attr, val){
   setContact(prev => {...contact, attr: val})
}

CodePudding user response:

You have to notify the dom, that the object has been rendered by recreating it or iterating it. See the snippet below.

function App() {
  const [contact, setContact] = React.useState({
    fName: "",
    lName: "",
    email: ""
  });

  function handleContact(event) {
    const { value, name } = event.target;
    setContact((prevValue) => {
      prevValue[name] = value;
      return { ...prevValue };
    });
  }
  return (
    <div className="container">
      <h1>
        Hello {contact.fName} {contact.lName}{" "}
      </h1>
      <p> {contact.email} </p>
      <form>
        <input
          name="fName"
          placeholder="First Name"
          value={contact.fName}
          onChange={handleContact}
        />
        <input
          name="lName"
          placeholder="Last Name"
          value={contact.lName}
          onChange={handleContact}
        />{" "}
        <input
          name="email"
          placeholder="Email"
          value={contact.email}
          onChange={handleContact}
        />{" "}
        <button> Submit </button>
      </form>
    </div>
  );
}

// Render it
ReactDOM.render(
    <App />,
    document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>

  • Related