如何使用 React 和 useEffect 更改数组中的位置?
How to change places in an Array using React and useEffect?
有一个包含 5 个元素的列表。默认情况下,列表(数组)应显示 ["A"、"B"、"C"、"D"、"E"]。元素应该每秒旋转一个位置:
1 秒后列表:["B", "C", "D", "E", "A"];
2 秒后:["C"、"D"、"E"、"A"、"B"];
3 秒后:[“D”、“E”、“A”、“B”、“C”];
我正在学习,我需要帮助。你会如何解决这个问题?这是我的错误解决方案:
import React, { useState, useEffect } from "react";
import "./App.css";
function App() {
const [term, setTerm] = useState();
const [letter, setLetter] = useState([]);
let array = ["A", "B", "C", "D", "E"];
useEffect(() => {
const interval = () =>
setInterval(() => {
array.push(array.shift());
setLetter(array);
}, 1000);
interval();
return clearInterval(interval);
}, [array]);
return (
<div className="center">
<input
type="text"
value={term}
onChange={(e) => setTerm(e.target.value)}
/>
{letter &&
letter.map((l, i) => {
return (
<ul key={l}>
<li>{l[0]}</li>
<li>{l[1]}</li>
<li>{l[1]}</li>
<li>{l[3]}</li>
<li>{l[4]}</li>
</ul>
);
})}
</div>
);
}
export default App;
我只是一个学习者,我被困住了,我需要帮助。它变化很快,就像每 50 毫秒。
我会分析答案并从中学习,因为我自己做不到。
这里发生的是你有一个 useEffect
附加到 array
的变化,它在间隔回调中多次变化。
- 更改:array.shift() -> 触发
useEffect
- 更改:array.push() -> 同时触发
useEffect
这复合并开始快速改变数组。
我建议使用数组副本或类似的东西。
setInterval(() =>
let copy = […array];
copy.push(copy.shift());
setLetter(copy);
array = copy
}, 1000);
只是另一个建议。我也会尽量不使用额外的 array
变量,因为该数据已经存储在 letter
中。
以下是我将如何做这件事。
const [letter, setLetter] = useState(["A", "B", "C", "D", "E"]);
useEffect(() => {
setTimeout(() =>
let copy = […letter];
copy.push(copy.shift());
setLetter(copy);
}, 1000);
}, [letter]);
我没有测试这个,所以我希望它能有所帮助。
我建议您避免修改数组。不是使用 push
和 shift
,而是通过 arr => [...arr .slice (1), arr [0]]
或使用 concat
:
生成数组的新版本
const {useState, useEffect} = React;
const App = () => {
const [letters, setLetters] = useState (["A", "B", "C", "D", "E"])
useEffect(() => {
const timer = setTimeout (
() => setLetters (arr => arr .slice (1) .concat (arr [0])),
1000
)
return () => clearTimeout (timer)
})
return (<div>{letters .join (' ')}</div>)
}
ReactDOM .render (<App/>, document .getElementById ("main"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="main"></div>
仅通过 setter 修改数据使事情更加一致。
请注意,即使不返回 clearTimeout
也能正常工作,但这可能是一个好习惯。
有一个包含 5 个元素的列表。默认情况下,列表(数组)应显示 ["A"、"B"、"C"、"D"、"E"]。元素应该每秒旋转一个位置:
1 秒后列表:["B", "C", "D", "E", "A"];
2 秒后:["C"、"D"、"E"、"A"、"B"];
3 秒后:[“D”、“E”、“A”、“B”、“C”];
我正在学习,我需要帮助。你会如何解决这个问题?这是我的错误解决方案:
import React, { useState, useEffect } from "react";
import "./App.css";
function App() {
const [term, setTerm] = useState();
const [letter, setLetter] = useState([]);
let array = ["A", "B", "C", "D", "E"];
useEffect(() => {
const interval = () =>
setInterval(() => {
array.push(array.shift());
setLetter(array);
}, 1000);
interval();
return clearInterval(interval);
}, [array]);
return (
<div className="center">
<input
type="text"
value={term}
onChange={(e) => setTerm(e.target.value)}
/>
{letter &&
letter.map((l, i) => {
return (
<ul key={l}>
<li>{l[0]}</li>
<li>{l[1]}</li>
<li>{l[1]}</li>
<li>{l[3]}</li>
<li>{l[4]}</li>
</ul>
);
})}
</div>
);
}
export default App;
我只是一个学习者,我被困住了,我需要帮助。它变化很快,就像每 50 毫秒。
我会分析答案并从中学习,因为我自己做不到。
这里发生的是你有一个 useEffect
附加到 array
的变化,它在间隔回调中多次变化。
- 更改:array.shift() -> 触发
useEffect
- 更改:array.push() -> 同时触发
useEffect
这复合并开始快速改变数组。
我建议使用数组副本或类似的东西。
setInterval(() =>
let copy = […array];
copy.push(copy.shift());
setLetter(copy);
array = copy
}, 1000);
只是另一个建议。我也会尽量不使用额外的 array
变量,因为该数据已经存储在 letter
中。
以下是我将如何做这件事。
const [letter, setLetter] = useState(["A", "B", "C", "D", "E"]);
useEffect(() => {
setTimeout(() =>
let copy = […letter];
copy.push(copy.shift());
setLetter(copy);
}, 1000);
}, [letter]);
我没有测试这个,所以我希望它能有所帮助。
我建议您避免修改数组。不是使用 push
和 shift
,而是通过 arr => [...arr .slice (1), arr [0]]
或使用 concat
:
const {useState, useEffect} = React;
const App = () => {
const [letters, setLetters] = useState (["A", "B", "C", "D", "E"])
useEffect(() => {
const timer = setTimeout (
() => setLetters (arr => arr .slice (1) .concat (arr [0])),
1000
)
return () => clearTimeout (timer)
})
return (<div>{letters .join (' ')}</div>)
}
ReactDOM .render (<App/>, document .getElementById ("main"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="main"></div>
仅通过 setter 修改数据使事情更加一致。
请注意,即使不返回 clearTimeout
也能正常工作,但这可能是一个好习惯。