graylagx2
graylagx2

Reputation: 80

Updating state from an array with react useState hook

Currently I'm using a state with key values. I'm updating that state from an array by looping over the array and setting state each loop. All this logic is happening from a function that is called from a onChange event from a text input.

The expected output from typing only the letter "c" in the text box is that two parameters in the state get changed. Each Key that starts with "c" has a value of false that should be switched to true.

The actual output is only one key value is changed

The array:

const unitList = [
    "cru",
    "co",
    "vr",
    "lr",
    "sr",
    "tg",
    "tra",
    "dh",
    "pl",
    "kh",
    "nh",
  ];

State:

const [optionList, setOptionList] = useState({
    cru: false,
    co: false,
    vr: false,
    lr: false,
    sr: false,
    tg: false,
    tra: false,
    dh: false,
    pl: false,
    kh: false,
    nh: false,
  });

User types in input box that onChange triggers this function function

const onSearchType = (e) => {
    var inputText = e.target.value.toUpperCase();
    unitList.forEach((unit, index) => {
      if (unit.substring(0, inputText.length).toUpperCase() === inputText)
        setOptionList({ ...optionList, [unit]: true });
    });
  };

If user types the letter c in the textbox I would expect the state value to return all items that start with c to be true so state would look like this

cru: true,
co: true,
vr: false,
lr: false,
sr: false,
tg: false,
tra: false,
dh: false,
pla: false,
kh: false,
nh: false,

Upvotes: 2

Views: 73

Answers (1)

Bas
Bas

Reputation: 1433

The issue with your code is that setOptionList({ ...optionList, [unit]: true }); this call is async. it would keeps overwriting the optionList. So if you set one unit to true, the next call will set every other unit back to its initial value due to the {...optionList} in the call.

To fix use a clone object of optionList and update that instead

const clone = { ...optionList };

 const onSearchType = (e) => {
    var inputText = e.target.value.toUpperCase();
    const clone = { ...optionList };
    unitList.forEach((unit, index) => {
      if (unit.substring(0, inputText.length).toUpperCase() === inputText)
        clone[unit] = true;
    });
    setOptionList(clone);
  };

https://codesandbox.io/s/mystifying-proskuriakova-6x4bxn?file=/src/App.js:0-975

Upvotes: 1

Related Questions