0

I am trying to save the results of a form entry on button click. I think the issue has to do with how react batches state updates?

My parent component needs to store an array of values obtained from its child, Input.

When a button is clicked, useEffect is called on each of the inputs in succession, requesting an update to the state in the parent component.

This update is carried out by getInput, which takes a value and an index value.

It iterates through the state array and replaces the value if the array index matches the provided index, or keeps the past value if it doesn't.

Then this array is set as the new state. Unfortunately it does not work this way.

import { myDataArray } from "./myData"

const Column = ({idx, requestInput, getInput}) => {
  const [values, setValues] = useState([...Array(7)]);
  const [request, setRequest] = useState(0)

  const getInput = (input, index) => {
    const newInput = values.map((d, i) => (i == index ? input : d)); // input : d <= this is supposed to keep past values if the index is not the same.
    setValues(newInput); //this overwrites the whole array 
  };

  return(
      <>
        <Button onClick={() => setRequest(request+1)} />
         {myDataArray.map( (d, idx) => (
           <Input key={d.title} request={request} idx={idx} getInput={getInput} />
         ))}
     </>
  )
}

const Input = ({request, idx, getInput}) => {

  const [value, setValue] = useState();
  const [error, setError] = useState(false);

  const handleChange = (event) => {
    if (event.target.value >= 0 && event.target.value <= 1) {
      setValue(event.target.value);
    } else {
      setError(true);
      setValue("");
      setTimeout(() => setError(false), 1500);
    }
  };

   useEffect(() => {
     getInput(value, idx);
   }, [request]); //this activates when button is clicked

   return (
        <input onChange={handleChange} />
  )
}

A sample of the data I get back, say I enter three rows of inputs in the first column:

['0.1', undefined, undefined, undefined, undefined, undefined, undefined]
[undefined, '0.123', undefined, undefined, undefined, undefined, undefined]
[undefined, undefined, '0.12314', undefined, undefined, undefined, undefined]

As you can see, the previous values are not being stored, even though they are supposed to be replaced.

Bigboss01
  • 438
  • 6
  • 21
  • You seem to be missing a `key` prop on your mapped `` components. React should be showing you a warning – Phil Nov 23 '22 at 01:09
  • @Phil, I will be sure to take care of that – Bigboss01 Nov 23 '22 at 01:15
  • I'd get right on it. It could be the source of your problems – Phil Nov 23 '22 at 01:17
  • @Phil no luck unfortunately. You got any other ideas? – Bigboss01 Nov 23 '22 at 01:19
  • 1
    my guess is that React processes all the children before rerendering and reevaluating the values of the parent. As such, each child will getInput on the initial `values` which is an array of 7 undefined elements. It will queue 7 setValues with only 1 value set at the corresponding index. Then when all those are processed you get an empty array with only the last index being set – user3252327 Nov 23 '22 at 01:20
  • @user3252327 nailed it. `getInput()` is only modifying the state based on the value in the current render. Should be `setValues((prev) => prev.map((d, i) => (i == index ? input : d)))` – Phil Nov 23 '22 at 01:26
  • @Phil, that worked perfectly, godsend – Bigboss01 Nov 23 '22 at 01:32

0 Answers0