#reactjs #use-state
Вопрос:
Я хочу иметь возможность вносить изменения в 2D-массив, но иметь возможность сохранять предыдущее состояние для последующего использования.
Например:
Первый щелчок: prevArray = [] currArray = [1,0,0],
Второй щелчок: prevArray = [1,0,0] currArray = [1,1,0],
Третий щелчок: prevArray = [1,1,0] currArray = [1,1,1]
import { useState, useEffect, useRef } from "react";
import "./App.css";
function App() {
const numRows = 3;
const numCol = 3;
const [currentGrid, setCurrentGrid] = useState(() =>
Array.from({ length: numRows }).map(() =>
Array.from({ length: numCol }).fill(0)
)
);
const prevGrid = usePrevious(currentGrid);
function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
}, [value]);
return ref.current;
}
const gridClick = (i, k) => {
const newGridState = [...currentGrid];
if (newGridState[i][k] === 1) {
newGridState[i][k] = 0;
} else {
newGridState[i][k] = 1;
}
setCurrentGrid([...newGridState]);
};
return (
<>
<div
className="grid"
style={{
display: "grid",
gridTemplateColumns: `repeat(${numRows},20px)`,
marginBottom: "20px",
}}
>
{currentGrid.map((rows, i) =>
rows.map((col, k) => (
<div
onClick={() => gridClick(i, k)}
style={{
width: 20,
height: 20,
backgroundColor: currentGrid[i][k] ? "blue" : "green",
border: "solid 1px black",
}}
></div>
))
)}
</div>
<div
className="grid"
style={{
display: "grid",
gridTemplateColumns: `repeat(${numRows},20px)`,
marginBottom: "20px",
}}
>
{prevGrid != null
? prevGrid.map((rows, i) =>
rows.map((col, k) => (
<div
style={{
width: 20,
height: 20,
backgroundColor: currentGrid[i][k] ? "blue" : "green",
border: "solid 1px black",
}}
></div>
))
)
: console.log("empty")}
</div>
</>
);
}
export default App;
В настоящее время состояние использования «prevGrid» просто копирует те же значения, которые находятся в «currentGrid».
Комментарии:
1. Вы должны переместить свой
onClick
обработчик вверх, чтобы он стал константой функции. Как есть, новая копия функции создается на каждой итерации карты.
Ответ №1:
Вы можете использовать какой-нибудь крючок, как в этом примере из useHooks.
В этом примере они использовали для получения предыдущего значения переменной счетчика:
import { useState, useEffect, useRef } from "react";
// Usage
function App() {
// State value and setter for our example
const [count, setCount] = useState(0);
// Get the previous value (was passed into hook on last render)
const prevCount = usePrevious(count);
// Display both current and previous count value
return (
<div>
<h1>
Now: {count}, before: {prevCount}
</h1>
<button onClick={() => setCount(count 1)}>Increment</button>
</div>
);
}
// Hook
function usePrevious(value) {
// The ref object is a generic container whose current property is mutable ...
// ... and can hold any value, similar to an instance property on a class
const ref = useRef();
// Store current value in ref
useEffect(() => {
ref.current = value;
}, [value]); // Only re-run if value changes
// Return previous value (happens before update in useEffect above)
return ref.current;
}
Комментарии:
1. Я внес изменения на основе вашего комментария (как видно из моего недавнего редактирования). Но все равно «prevGrid» отражает текущее состояние как «currentGrid». Может ли это иметь какое-то отношение к тому, как я обновляю текущую сетку? Вот ссылка на код в песочнице: codesandbox.io/s/damp-https-ikqiz .