Home > Net >  Difficulty updating state onChange in a Select tag React
Difficulty updating state onChange in a Select tag React

Time:06-28

I have a simple app to Generate a Random color. But it only updates on the next change and I can't figure out how to get an updater function to work.

  const handleHueChange = (e) => {
    const newHue = e.target.value;
    setHueColor(newHue);
    setColor(randomColor({ hue: hueColor, luminosity: lum }));
    console.log(color, hueColor, lum);
  };

There is the function and here it the select

<form>
        <select
          name="hue"
          value={hueColor.value}
          onChange={(e) => handleHueChange(e)}
        >
          {hue.map((hue, idx) => (
            <option key={idx}>{hue}</option>
          ))}
        </select>
      </form>

And here is a link to the code sandbox

https://codesandbox.io/s/brave-austin-ujv5xw?file=/src/App.js:1414-1673

The useeffect is giving the right value but it's only updating on the next render.

CodePudding user response:

Inside handleHueChange you are updating hueColor and in next line you were thinking that you can use that new state immediately so you wrote setColor(randomColor({ hue: hueColor, luminosity: lum }));, but hueColor you passed here is still old one because you are reading it from clousure, meaning only after rerender you will be able to access that new state. Solution is to just replace that line with setColor(randomColor({ hue: newHue, luminosity: lum })); - as you can see here I am using newHue instead of hueColor in order to update colors.

CodePudding user response:

You are using react 18 and in this version react will batch the changes, which means that react will apply your multiple setState together so you have to use setColor in a useEffect and remove that from handleChanges, something like this:

useEffect(() => {
  setColor(randomColor({ hue: hueColor, luminosity: lum }));
}, [hueColor, lum]);

const handleHueChange = (e) => {
  const newHue = e.target.value;
  setHueColor(newHue);
};

const handleLumChange = (e) => {
  const newLum = e.target.value;
  setLum(newLum);
};
  • Related