Home > Software design >  After setting initial state, click on update function getting same value
After setting initial state, click on update function getting same value

Time:09-25

I am updating a state by click on button. before there is a default value as well. when i click on update button same value updates again. any one show me the correct way to handle? for my case 0 and 1 are same value

here is the code :

import { useState } from "react";
import "./styles.css";

export default function App() {
  const names = ["Arif", "Afi", "Afzil", "Adil"];
  const [num, setNum] = useState(0);
  const [name, setName] = useState(names[num]);

  const Update = (i) => {
    setNum(num   i);
    setName(names[num]);
  };

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>{name}</h2>
      {num} <br />
      <br />
      <button onClick={() => Update(1)}>Update</button>
      <br />
      <br />
      <button onClick={() => Update(-1)}>Downdate</button>
    </div>
  );
}

Live Demo

CodePudding user response:

https://codesandbox.io/s/bold-tdd-92f2h?file=/src/App.js:0-629

const names = ["Arif", "Afi", "Afzil", "Adil"];

export default function App() {
  const [num, setNum] = useState(0);
  const [name, setName] = useState(names[num]);

  const Update = (i) => setNum(num   i);

  useEffect(() => {
    setName(names[num]);
  }, [num, setName]);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>{name}</h2>
      {num} <br />
      <br />
      <button onClick={() => Update(1)}>Update</button>
      <br />
      <br />
      <button onClick={() => Update(-1)}>Downdate</button>
    </div>
  );
}

Here is a working example. React state updates are asynchronous, so calling them one after another in the same function tends to cause issues. In this case, when you call setName inside your update function, num is still the old value.

When you want state to change depending on some other state, you should use the useEffect hook. Heres's the relevant doc:

https://reactjs.org/docs/hooks-effect.html

EDIT: Alex Wayne is right and you do not need two separate states. Still, do read on useEffect for when you want to do side-effects like this.

CodePudding user response:

It's because they happen "at the same time". So, num still has the same value when you try to setName.

The recommendation would be:

 const Update = (i) => {
    const newValue = (num   i) % names.length;
    setNum(newValue);
    setName(names[newValue]);
  };

You can see how it works: https://codesandbox.io/s/blissful-danilo-h3cf2?file=/src/App.tsx:227-356

CodePudding user response:

setNum(num   i);
setName(names[num]);

Here you first set the state via setNum to num 1. But num is a local variable. Think of it as a snapshot of your state's value at the time your component rendered. num won't have the new value of the updated state until the next render.

So when you do this the first time:

setNum(num   i);

You set 0 1 in state, but num is still 0.

Then you do:

setName(names[num]);

And since num is still 0, the name being set in state doesn't change.


The real problem here is that you have too much state. The name can be derived from the num, so you don't need to store the name in state at all.

For example:

export default function App() {
  const names = ["Arif", "Afi", "Afzil", "Adil"];
  const [num, setNum] = useState(0);

  // removed [name, setName] entirely

  const Update = (i) => {
    setNum(num   i);
  };

  // lookup name using the stateful value `num`
  const name = names[num]

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>{name}</h2>
      {num} <br />
      <br />
      <button onClick={() => Update(1)}>Update</button>
      <br />
      <br />
      <button onClick={() => Update(-1)}>Downdate</button>
    </div>
  );
}

Note that there is only one state, and we simply look up the the name as we render.

Sandbox

CodePudding user response:

State dependencies should be handled by useEffect when using Functional Components.

import { useState, useEffect } from "react";
import "./styles.css";

export default function App() {
  const names = ["Arif", "Afi", "Afzil", "Adil"];
  const [num, setNum] = useState(0);
  const [name, setName] = useState(names[0]);

  useEffect(()=>{
    setName(names[num]);
  }, [num])


  const Update = (i) => {
    setNum(num   i);
  };

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>{name}</h2>
      {num} <br />
      <br />
      <button onClick={() => Update(1)}>Update</button>
      <br />
      <br />
      <button onClick={() => Update(-1)}>Downdate</button>
    </div>
  );
}
  • Related