看来,记录在控制台上的对象与在上显示的内容不匹配,下面这个简单的示例让我感到困惑。在这里,按钮切换数组的顺序,并作出反应似乎呈现上一个列表。
===更新3 ====
cuprite是对象同情,其中setState(list=>list.push(12))会变异列表,但不会触发setState,因为列表的id仍然是相同的。
如果您将状态挂钩更新为与当前状态相同的值,则React将在不呈现子状态或触发效果的情况下退出。(React使用Object.is比较算法。) 反应useState文档
===更新2 ====
我想我找到了解决办法。罪魁祸首似乎是对象的可更改性,解决方法是在溶液砂箱中创建排序列表的深度副本。我认为我发现了一种未定义的反应行为,因为列表的可更改性不应导致console.log(list)和<h1>list</h1>之间的任何差异,如下图所示。ReactJS中状态数组的正确修改

===更新1 ====
沙盒,它包含与下面所示代码相同的代码。
我的排序函数没有什么问题!如果是升序,那么应该首先使用较小的元素,这意味着比较函数(e1,e2)=>e1-e2是正确的。
如果compareFunction(a,b)返回小于0,则对低于b的索引排序a(即a优先)。比较函数Mozilla
const {useState, useEffect, useReducer} = React;
function App() {
const [list, setList] = useState([0,1]);
const [isAscending, toggle] = useReducer(isAscending=>!isAscending, true);
// update the order of the list
useEffect(()=>{
if (isAscending) {
setList(list.sort((e1,e2)=>e1-e2));
} else {
setList(list.sort((e1,e2)=>e2-e1));
}
},[list, isAscending]);
// render
return (
<div>
{console.log("list[0] should be",list[0])}
<button onClick={toggle}>{isAscending?"Ascending":"Descending"}</button>
<h1>list[0]: {list[0]}</h1>
</div>
)
}
ReactDOM.render(<App/>, document.querySelector('.App'));<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div class='App'/>
发布于 2020-11-03 08:55:21
根据MDN,javascript排序函数会对数组进行变异。
sort()方法对数组的元素进行排序,并返回排序后的数组。
当你写:
setList(list.sort((e1, e2) => e1 - e2));在setList对其进行变异之前,您是在变异列表。
setList检查给定的值是否与以前的值不同,然后进行呈现。
但是setList认为没有什么不同,因为list值已经通过排序方法更新了。
正因为如此,渲染似乎落后了一步。
所以你应该写:
setList([...list].sort((e1, e2) => e1 - e2));还有一件事:
我觉得你应该改变一下
{isAscending ? "Ascending" : "Descending"}至
{isAscending ? "Descending" : "Ascending"}因为它是一个切换按钮
发布于 2020-11-02 13:34:46
您的初始顺序是升序。单击该按钮时,第一次切换要从升序移动到降序的顺序。
这意味着
if (isAscending) {
// Logic for descending should come here
setList(list.sort((e1, e2) => e2 - e1));
} else {
// Logic for ascending should come here
setList(list.sort((e1, e2) => e1 - e2));
}检查这里的代码,让我知道这是否是你要找的。代码沙箱:排序列表不呈现
发布于 2020-10-25 06:35:29
在list回调处有useEffect值的闭包,应该将其添加到dep数组中:
function App() {
const [list, setList] = useState([0, 1]);
const [isAscending, toggle] = useReducer((isAscending) => !isAscending, true);
useEffect(() => {
setList(list.sort((e1, e2) => (!isAscending ? e1 - e2 : e2 - e1)));
}, [list, isAscending]);
return (
<div>
<button onClick={toggle}>
{isAscending ? "Ascending" : "Descending"}
</button>
<pre>{JSON.stringify(list)}</pre>
</div>
);
}请注意,如果您有
eslint,您应该得到一个警告。
https://codesandbox.io/s/react-template-forked-08eft?file=/index.js:99-684
https://stackoverflow.com/questions/64520983
复制相似问题