所以我有这个自定义钩子:
import sortBy from 'lodash/fp/sortBy';
import { useState, useEffect } from 'react';
/**
* Custom effect that enables data sorting.
* It is triggered every time when sort order or data has changed.
*
* @param {*} initialSort
* @param {*} data
*/
function useSorting(initialSort, data) {
const [sortOrder, setSortOrder] = useState(initialSort);
const [sortedData, setSortedData] = useState([]);
useEffect(() => setSortedData(sortBy(sortOrder, data)), [data, sortOrder]);
return [sortedData, sortOrder, setSortOrder];
}
export default useSorting;
它接受要排序的数据和排序顺序。每次通过setSortOrder
更改排序顺序或提供新的data
时,它应该进行排序并更新sortedData
。
这是正确的方法吗?我的意思是,有一个useEffect
正在倾听[data, sortOrder]
的变化?
如果没有React钩子,我会使用componentDidUpdate
并手动检查是否更改了sortOrder
或data
并使用新的this.setState
做sortedData
。看起来它做了类似的事情
你的例子应该有效,这就是按顺序发生的事情,例如当你传递新的data
或者你使用setSortOrder
时。
1 - 你到达钩子的代码里面
2 - 你勾使用setSortedData
更新它的sortedData
状态
3 - 它将陈旧的sortedData
返回到您的组件(因为它在被修改之前从useState
读取)
4 - 对setSortedData
的调用启动,更改状态中的数据,触发组件的新渲染,这将再次使用您的钩子,钩子将提供正确版本的sortedData
。
简而言之,您有一个额外的渲染。如果你想阻止它,你可以使用useMemo
,如下:
function useSorting(initialSort, data) {
const [sortOrder, setSortOrder] = useState(initialSort);
const sortedData = useMemo(() => sortBy(sortOrder, data), [data, sortOrder]);
return [sortedData, sortOrder, setSortOrder];
}
您的组件将立即获得已排序的数据,而无需经过额外的渲染循环,并且您仍然可以在相关信息发生变化时调用排序函数(data
,sortOrder
)。