J.K*_*.Ko 0 javascript sorting reactjs react-hooks
我正在尝试执行以下操作的 react/react 钩子编写代码。
从父组件获取对象数组作为 prop 使用useState钩子将其设置为状态。根据预期的过滤器(时间和评级)对状态进行排序,并重新渲染子组件。我看到的是,下面的代码在排序后更新了状态,但是即使状态更新了,依赖于该状态的子组件也不会重新渲染。我认为子组件会在状态改变时自动重新渲染?
import React, {useState} from 'react';
import ProfilePostspreview from './ProfilePostspreview';
function ProfileNavigation(props){
const [newarray, setnewarray]=useState(props.parray); //'parray' object passed as props and saved as 'newarray' state
const otc = () => { //Function to sort the state by time and set a new state
let k=newarray;
setnewarray(k.sort((a, b) => (a.time > b.time) ? -1 : 1 ));
}
const orc = () => { //Function to sort the state by rating and then time and set a new state
let k=newarray;
setnewarray(k.sort((a, b) => (a.rating > b.rating) ? -1 : (a.rating === b.rating) ? ((a.time > b.time) ? -1 : 1) : 1 ));
}
return (
<div>
<div className="sm_options"> //Component to trigger the otc and orc functions
<div className="sm_button" id="order_t" onClick={otc}>Sort by time</div>
<div className="sm_button" id="order_r" onClick={orc}>Sort by rating</div>
</div>
<div className="posts_preview_columns_p"> //This is dependent on the 'newarray' state but is not re-rendering even after the state is sorted and updated?
{newarray.map(na=>
<ProfilePostspreview
postThumbnail={na.photolink}
rating={na.rating}
time={na.time}
target={na.target}
/>
)}
</div>
</div>
);
}
export default ProfileNavigation;
Run Code Online (Sandbox Code Playgroud)
这可能是什么原因?代码是否有问题,或者对状态进行排序是否被认为不足以让 React 重新渲染子组件?如果是后者,如何在排序后强制重新渲染?
有什么建议吗?谢谢!
该
sort()方法对数组的元素进行原地排序并返回排序后的数组。默认排序顺序是升序,建立在将元素转换为字符串,然后比较它们的 UTF-16 代码单元值序列的基础上。
这对您来说意味着存储在数组中的元素的顺序可能会改变,但数组是原位排序的,这意味着返回相同的数组引用(与返回新数组的其他数组函数不同)。
React 协调通过检查 state 和 props 发生,并做出一个整体假设,如果下一个 state/prop 引用没有改变,那么值没有改变,因此返回最后计算的渲染 DOM。这是更新反应状态的重要细节……每次更新都需要引用一个新对象。
在你的情况你只是保存在参考当前阵列中的状态,变异它,并重新保存它。由于引用是稳定的并且不会改变,所以 react 不会重新渲染。
const otc = () => {
let k = newarray; // <-- saved array reference!!
setnewarray(k.sort((a, b) => (a.time > b.time) ? -1 : 1 ));
}
Run Code Online (Sandbox Code Playgroud)
正确的反应方式是将当前数组值复制到一个新数组中,这样它就会有一个新的对象引用。
const otc = () => {
const newSortedArray = [...newArray].sort(
(a, b) => (a.time > b.time) ? -1 : 1
); // spread old array values into new array, then sort
setNewArray(newSortedArray);
}
Run Code Online (Sandbox Code Playgroud)