Home > Software engineering >  useState hook not "reacting" when state variable modified
useState hook not "reacting" when state variable modified

Time:08-08

I have created a React application to test out the useState hook.

This the variable of concern:

let [blocks, setBlocks] = useState([
    {text: "Hello", id: 1},
    {text: "This is google", id: 2},
    {text: "Wassup", id: 3},
    {text: "Last One", id: 4}
  ]);
I've displayed this using the map function as follows:

return (
<div className="App">
  {blocks.map((block) => (
    <div className='block-element'>{block.text}</div>
    ))}
    <button onClick={clickFunc}>ClickToChange</button>
</div>
  );

As far as I've understood, to make any change in the webpage we have to pass the new-data into setBlocks() and wherever "blocks" was used will be updated.

I tried the following clickFunc() to do so:

const clickFunc = ()=>{
    blocks[1].text = "Go Home";
    setBlocks(blocks);
    console.log(blocks);
  }
I expected the output (onclicking the button) to be:

Hello

Go Home

Wassup

Last One

But nothing changed.

Surprisingly when I used the following (similar looking) clickFunc():

const clickFunc = ()=>{
    blocks = [
      { text: "Hello", id: 1 },
      { text: "Go Home", id: 2 },
      { text: "Wassup", id: 3 },
      { text: "Last One", id: 4 }
    ];
    setBlocks(blocks);
    console.log(blocks);
  }

And it worked perfectly as expected. On click output:

Hello

Go Home

Wassup

Last One

CodePudding user response:

NEVER mutate state directly.

The following code block is mutation and wrong. Javascript is kind of like some other programming languages where only the reference of the object is stored in the memory. So when you mutate the object instead of creating a new one, you are not really changing the content of the object in memory, because it still has the same value(reference) as before.

const blocks = [{text: 'one'}];
blocks[0].text = 'two';

You should create a new object and assign it to state using React setState callback:

setBlocks(blocks => {
    clonedBlocks = [ ...blocks];
    clonedBlocks[1]= { ...blocks[1], text: "Go Home" };
    return clonedBlocks;
});

Or any other way that does not mutate the state directly.

CodePudding user response:

React state is immutable

if you mutate the state react will not know that state is changed

first you need to copy the state using Spread syntax and change it

const clickFunc = () => {
    setBlocks(prevBlocks => {
        const shallowCopy = [...prevBlocks]

        shallowCopy[1].text = "Go Home";

        return shallowCopy
    });
}
  • Related