После установки начального состояния нажмите на функцию обновления, получив то же значение

#reactjs

Вопрос:

Я обновляю состояние, нажав на кнопку. до того, как появится значение по умолчанию. когда я нажимаю на кнопку обновить, снова обновляется то же значение. кто-нибудь покажет мне, как правильно обращаться? для моего случая 0 и 1 имеют одинаковое значение

вот код :

 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>
  );
}
 

Живая демонстрация

Комментарии:

1. setNum не установит значение мгновенно. он установит свое значение только при следующем рендеринге, пожалуйста, ознакомьтесь с документами react useState. docs

Ответ №1:

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

Здесь вы сначала устанавливаете состояние через setNum в num 1 . Но num является локальной переменной. Думайте об этом как о моментальном снимке значения вашего состояния во время визуализации вашего компонента. num не будет иметь нового значения обновленного состояния до следующего рендеринга.

Поэтому, когда вы делаете это в первый раз:

 setNum(num   i);
 

Вы находитесь 0 1 в состоянии, но num все еще 0 находитесь .

Тогда вы делаете:

 setName(names[num]);
 

И поскольку num остается 0 неизменным , имя, заданное в состоянии, не меняется.


Настоящая проблема здесь в том, что у вас слишком много государства. Имя может быть производным от num , поэтому вам вообще не нужно хранить имя в состоянии.

Например:

 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>
  );
}
 

Обратите внимание, что существует только одно состояние, и мы просто ищем имя при визуализации.

Песочница

Комментарии:

1. Я согласен. но я получаю эту ошибку: Uncaught Error: Cannot add node 1 because a node with that id is already in the Store. у вас есть какие-либо идеи? когда я добавляю условие if https://codesandbox.io/s/funny-gauss-njomz?file=/src/App.js:206-345 , обновите и проверьте консоль, нажав кнопку

2. @3gwebtrain Эта ошибка, похоже, исходит от инструментов разработчика React, которых нет в производстве. Это может иметь какое-то отношение к тому, как песочница кода включает реакцию. Я не уверен, что это значит, но, похоже, это не вызывает проблем, и, вероятно, этого не будет в отдельном приложении react. Я бы не стал об этом беспокоиться.

Ответ №2:

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>
  );
}
 

Вот рабочий пример. Обновления состояния реакции являются асинхронными, поэтому их вызов один за другим в одной и той же функции, как правило, вызывает проблемы. В этом случае, когда вы вызываете setName внутри своей update функции, num все равно остается старое значение.

Когда вы хотите, чтобы состояние менялось в зависимости от какого-то другого состояния, вам следует использовать useEffect крючок. Вот соответствующий документ:

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

ПРАВКА: Алекс Уэйн прав, и вам не нужны два отдельных состояния. Тем не менее, прочтите об эффекте использования, когда вы захотите использовать побочные эффекты, подобные этому.

Ответ №3:

Это потому, что они происходят «в одно и то же время». Таким образом, num по-прежнему имеет то же значение, когда вы пытаетесь установить имя.

Рекомендация будет заключаться в следующем:

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

 

Вы можете увидеть, как это работает: https://codesandbox.io/s/blissful-danilo-h3cf2?file=/src/App.tsx:227-356