Update state with multiple input

I'm stucked on updating state on react with multiple input. Here is how the state looks like

const [state, setState] = useState({
        documents: [
            {
                nom: 'mamy',
                contact: '1234567890',
                numAudit: 'XXX/1234',
                email: '[email protected]',
            },
            {
                nom: 'tsiry',
                contact: '5555237890',
                numAudit: 'XXX/1235',
                email: '[email protected]',
            },
            {
                nom: 'fenohasina',
                contact: '1234123890',
                numAudit: 'XXX/1236',
                email: '[email protected]',
            },
        ],
    });

I have this function to handle multiple input and update the state

const handleChange = (e) => {
        const value = e.target.value
        //const newDoc = [...documents, { [e.target.name]: value }]
        //documents = newDoc
        setStateValue({
            ...stateValue,
            documents: { ...stateValue.documents, [e.target.name]: value }
        })

    }

But rather than getting an object witch is supposed to be pushed in the documents, it creates a field for each input fied.

Here is the state updated by this function looks like, with is not good

{
        documents: [
            {
                nom: 'fenohasina',
                contact: '1234123890',
                numAudit: 'XXX/1236',
                email: '[email protected]',
            },
            nom:'new value',
            contact:'new value',
            numAudit:'new value',
            email:'new value',
        ],
    }

And here is the state that i'm expected to get

{
            documents: [
                {
                    nom: 'fenohasina',
                    contact: '1234123890',
                    numAudit: 'XXX/1236',
                    email: '[email protected]',
                },
                {
                    nom:'new value',
                    contact:'new value',
                    numAudit:'new value',
                    email:'new value',
                }
            ],
        }

If you can help me wiht the function handleChange it'll save my life. THANKS

Upvotes: 0

Views: 633

Answers (3)

bakar_dev
bakar_dev

Reputation: 996

Check it out, i have implemented for you, you need to store all input values into separate object and then merge new document with all previous documents on some action like button click. Codesandbox: https://codesandbox.io/s/confident-pascal-lcejd?file=/src/App.js

import React, { useState, useEffect } from "react";
import "./styles.css";

export default function App() {
  const [values, setValues] = useState({
    nom: "",
    contact: "",
    numAudit: "",
    email: ""
  });
  const [state, setState] = useState({
    documents: [
      {
        nom: "mamy",
        contact: "1234567890",
        numAudit: "XXX/1234",
        email: "[email protected]"
      },
      {
        nom: "tsiry",
        contact: "5555237890",
        numAudit: "XXX/1235",
        email: "[email protected]"
      },
      {
        nom: "fenohasina",
        contact: "1234123890",
        numAudit: "XXX/1236",
        email: "[email protected]"
      }
    ]
  });

  const onChangeFunc = e => {
    const newValues = { ...values, [e.target.name]: e.target.value };
    setValues(newValues);
  };

  const onAdd = () => {
    setState({ documents: [...state.documents, values] });
  };

  //just to display updated state
  useEffect(() => {
    console.log("state now", state);
  }, [state]);

  return (
    <div className="App">
      <input
        type="text"
        name="nom"
        placeholder="nom"
        value={values["nom"]}
        onChange={onChangeFunc}
      />
      <br />
      <input
        type="text"
        name="contact"
        placeholder="contact"
        value={values["contact"]}
        onChange={onChangeFunc}
      />
      <br />
      <input
        type="text"
        name="numAudit"
        placeholder="numAudit"
        value={values["numAudit"]}
        onChange={onChangeFunc}
      />
      <br />
      <input
        type="text"
        name="email"
        placeholder="email"
        value={values["email"]}
        onChange={onChangeFunc}
      />
      <br />
      <button onClick={onAdd}>Add New</button>
    </div>
  );
}

Upvotes: 1

brijesh-pant
brijesh-pant

Reputation: 1145

Your implementation doesn't look fully correct. Adding data todocuments array should be done on say button click, not on handleChange

Take a look at this example here: https://codesandbox.io/s/nice-moore-e3ny0?file=/src/App.js

import React from "react";

export default function App() {
  const [state, setState] = React.useState({
    documents: [{ name: "John", age: 12 }]
  });

  const [inputInfo, setInputInfo] = React.useState({});
  const handleChange = event => {
    event.persist();
    setInputInfo(inputInfo => ({
      ...inputInfo,
      [event.target.name]: event.target.value
    }));
  };

  const handleClick = () => {
    setState(state => ({
      ...state,
      documents: [...state.documents, inputInfo]
    }));
    setInputInfo({});
  };

  return (
    <div className="App">
      {state.documents.map(({ name, age }) => (
        <p>
          {name}-{age}
        </p>
      ))}
      <input
        name="name"
        placeholder="name"
        value={inputInfo.name}
        onChange={handleChange}
      />
      <input
        type="number"
        name="age"
        placeholder="age"
        value={inputInfo.age}
        onChange={handleChange}
      />
      <button onClick={handleClick}>Add</button>
    </div>
  );
}

Upvotes: 1

Tarukami
Tarukami

Reputation: 1160

Your function looks fine and output is as expected to be because it does not know what object inside of an array must be updated. Two possible solutions which I can see:

  1. If you want to add the whole new object you have to collect all the new values into new object until it is done. When it is finished, update the state with new object containing all the fields inside.
  2. Or if you want to add fields one by one as you do now, you can have a function which will find the object inside your state to be updated. In other words, you shoud have an id or email to find the proper object inside your state and then update the proper field.

Upvotes: 1

Related Questions