#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.
у вас есть какие-либо идеи? когда я добавляю условие ifhttps://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