0

I have a following state declared

 const [state, setState] = useState({
        title: "",
        subtitle: "",
        products: [],

state.products is an array of objects e.g.

products = [{a: "", b: "", c: ""}]

On form submit I want to take the input values and append them to the products array as an object.

My submit handler doesn't do what I want. Where have I gone wrong?

function handleSubmit(e) {
  const newProduct= {"a": e.target[0].value, "b": e.target[2].value, "c": e.target[1].value}
            setState({...state, products: [...state.products, newProduct]})

}
ProjectAlice
  • 71
  • 1
  • 4
  • what your expected output? – Bhavesh Daswani Jul 22 '22 at 13:52
  • *"My submit handler doesn't do what I want."* - Then what **does** it do? Are there any errors on the browser console? Is the handler function invoked at all? What is the new state value that it sets? What specifically happens? How specifically are you observing that there's a problem? Can you update the question to a [mcve] which demonstrates the problem? – David Jul 22 '22 at 13:54
  • @Bhavesh All product "a" keys get displayed in another input field which is working and the newly added key is displayed but if I console.log(state.products) the array stays the same, no new object added. I should mention that the initial data is fetched from another endpoint and then displayed in several input fields. I want to be able to post the new data. – ProjectAlice Jul 22 '22 at 13:56
  • can you provide full code of your component, I would like to reproduce on my side and test it. – Bhavesh Daswani Jul 22 '22 at 14:03

2 Answers2

0

You could do something like this

function handleSubmit(e) {
  const newProduct = {
    a: e.target[0].value,
    b: e.target[2].value,
    c: e.target[1].value
  };
  setState(prevState => ({
    ...prevState,
    products: [...prevState.products, newProduct]
  }));
}
Pratik Wadekar
  • 1,198
  • 8
  • 15
0

If you console.log outside of the state setter, you will not get the latest copy of the state, i.e.,

const Component = () => {
    const [state, setState] = useState(...);

    function handler(e) {
        ...
        setState(...);
        console.log(state.products); // This will print the previous version of the state.
    }
}

This is the expected behavior as state setters are asynchronous. So instead I log like this,

    function handler(e) {
        const newProduct = ...;
        ...
        setState(prevState => {
            const newState = {...prevState, products: [...prevState.products, newProduct]}; // update state as you did before.
            console.log(newState);

            return newState;
        });
        
    }

You can also use

useEffect(() => {
    console.log(state)
}, [state, state.products]);
Yash Sonalia
  • 378
  • 2
  • 8