skip to Main Content

I am new to react and trying to understand the useState hook. What I am trying to do is, I have a input type text field and a button. On click of button, I am trying to push the entered value to an array. But currently on doing so, its adding the value to the array but clearing it back and making the array empty. Could any one please tell me why its happening and how to fix it. Below is what I have done.

import React, { useState } from "react";

const HookCounter5 = () => {
  const [item, setItem] = useState([]);
  const [name, setName] = useState({ firstName: "" });
  const handlePushNameToArray = () => {
    setItem(...item, name.firstName);
  };
  return (
    <div>
      <form>
        <input
          type="text"
          value={name.firstName}
          onChange={(e) => setName({ ...name, firstName: e.target.value })}
        ></input>
        <button onClick={handlePushNameToArray}>Push to array</button>
        <div>{JSON.stringify(item)}</div>
      </form>
    </div>
  );
};

export default HookCounter5;

2

Answers


  1. You are not using the spread operator correctly. While updating state, use array square brackets.

    setItem([...item, name.firstName]);
    

    This method wouldn’t work if component is not re rendered after updating name state(this happens because react bathces all the state changes and then updates).
    In that case, you can use the other form of useState syntax like below:

    setItem(prevState => [...prevState, name.firstName]);
    
    

    Use the same for name also.

    Login or Signup to reply.
  2. Actually, it was getting pushed to to the array except the state was set to its inital value because the whole page refreshed.

    • Your button tag is within a form tag. All buttons inside a form tag submits the form, which reloads the page if e.preventDefault() is not present.

    Solutions (please do either one only)

    • If you want to keep it inside the form tag, give it a type of button
    • Pass handlePushNameToArray as an onSubmit on the form tag and remove the onClick callback from the button
    • Simply move the button out of the form tag.

    Here’s the working code

    import "./styles.css";
    import { useState } from "react";
    
    export default function App() {
      const [item, setItem] = useState([]);
      const [name, setName] = useState({ firstName: "" });
      const handlePushNameToArray = () => {
        setItem((prev) => [...prev, name.firstName]);
      };
      return (
        <div>
          <form>
            <input
              type="text"
              value={name.firstName}
              onChange={(e) => setName({ ...name, firstName: e.target.value })}
            ></input>
            <div>{JSON.stringify(item)}</div>
          </form>
          <button onClick={handlePushNameToArray}>Push to array</button>
        </div>
      );
    }
    

    Here’s how I would do it

    1. Use onSubmit to call handlePushNameToArray just by hitting enter
    2. Clear input field on submit
    3. Show as list
    export default function App() {
          const [item, setItem] = useState([]);
          const [name, setName] = useState({ firstName: "" });
        
          const handlePushNameToArray = (e) => {
            e.preventDefault();
            setItem((prev) => [...prev, name.firstName]);
            setName({ firstName: "" });
          };
        
          return (
            <main>
              <form onSubmit={(e) => handlePushNameToArray(e)}>
                <input
                  type="text"
                  value={name.firstName}
                  onChange={(e) => setName({ ...name, firstName: e.target.value })}
                ></input>
                <button>Push to array</button>
              </form>
              <ul>{item && item.map((name) => <li>{name}</li>)}</ul>
            </main>
          );
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search