#reactjs #react-hooks
Вопрос:
Значение с именем «a» в нижнем коде ведет себя не ожидаемо на локальном, а не на статическом сайте.
Я ожидаю, что a увеличивается на 100 в секунду, но увеличивается на 200 в секунду.
Эта проблема возникает при запуске приложения с помощью следующих команд.
next dev
react-scripts start
Как я могу решить эту проблему? (И является ли это ожидаемым поведением крючков react?) Если возможно, не используйте useReducer.
Я уже прочитал этот сайт.
import { memo, useEffect, useState, VFC } from "react";
const StateLearning: VFC = () => {
const [a, setA] = useState([
[1, 2],
[0, 4],
]);
// This moved expectedly
// useEffect(() => {
// const eff = setInterval(() => {
// a[1][0] = 100;
// console.log('add 100')
// setA([...a]);
// }, 1000);
// return () => clearInterval(eff);
// }, [a]);
// a[1][0] moves 0→100→300→500→……
useEffect(() => {
const eff = setInterval(() => {
setA((prev) => {
prev[1][0] = 100;
console.log("add 100");
console.info(prev)
return [...prev];
});
}, 1000);
return () => clearInterval(eff);
}, []);
return (
<div style={{ margin: "10%" }}>
<div>
<div>
{a[0][0]}, {a[0][1]}
</div>
<div>
{a[1][0]}, {a[1][1]}
</div>
</div>
</div>
);
};
P.S.
Кроме того, я также хочу изменить значение другой функции с помощью, например, onClick. последний код является примером.
…
// called by like onclick
const multiple = () => {
setA((p) => {
const newArray = [
[
p[0][0] * p[0][0] p[0][1] * p[1][0],
p[0][0] * p[0][1] p[0][1] * p[1][1],
],
[
p[1][0] * p[0][0] p[1][1] * p[1][0],
p[1][0] * p[0][1] p[1][1] * p[1][1],
],
];
return [...newArray];
});
};
…
Комментарии:
1. Не уверен, в чем проблема с двойным обновлением, но если вы хотите иметь истинное обновление неизменяемого состояния, вам нужно это сделать
prev => prev.map((row, i) => i === 1 ? row.map((col, j) => j === 0 ? (col 100) : col) : row)
. В противном случае вы мутируете вложенный массив без создания копии codesandbox.io/s/agitated-wilson-fd89d?file=/src/App.js2. При изготовлении подобных часов эта проблема фатальна. (Я был смущен тем, что матрица не была ожидаемо обновлена в другом случае, поэтому протестирована в простом случае.) Ваш комментарий очень полезен, и я действительно ценю ваши комментарии.
Ответ №1:
Я создал эту песочницу, https://codesandbox.io/s/strange-mahavira-co66j
Мне кажется, это работает
useEffect(() => {
const eff = setInterval(() => {
a[1][0] = 100
setA([...a])
}, 1000)
return () => {
clearInterval(eff)
}
}, [setA])
Вам не нужно обязательно использовать prev
, потому a
что это объект в вашем случае. Обычно проблема возникает с примитивным значением.
Комментарии:
1. OP необходимо использовать форму версии обновления
setState
. Наличие объекта в качестве значения не меняет того, почему нам нужно его использовать. В настоящее время это работает только потому, что вы изменяете значение вложенного массива без создания копии с исходным значением, записанным в области обратного вызова. Если у кого-то есть другой способ редактирования значений, возникнет целая куча проблем. codesandbox.io/s/heuristic-tdd-77xm2?file=/src/App.js2. это, кажется, работает, но я также хочу изменить значение » a » с помощью другой функции, такой как onClick(матрица, кратная). Когда функция setinterval перемещается, эта функция не применяла изменение функции onclick.