我使用React + d3js在svg上呈现数据,我有一个包含如下数据的大数组
const arrayItemExample = {
id: 1,
text: 'Some Text for node',
x: 100,
y: 300,
selected: false,
dragging: false
}这类元素的清单可达数万份。主要问题是,当我单击或拖动呈现的元素时,会更新该元素上的数据:
const handleDragStart = useCallback((id)=>{
setData(data=>{
return data.map(item=>{
if(item.id === id){
return {
...item,
dragging: true
}
}
return item
})
})
},[])
const handleSelect = useCallback((id)=>{
setData(data=>{
return data.map(item=>{
if(item.id === id){
return {
...item,
selected: true
}
}
return item
})
})
},[])这两个函数都能很好地处理少量的数据,但是如果页面上有100个或更多的元素,那么单击或拖动元素会在元素重绘过程中减缓页面的速度。
是否有任何方法通过重绘其唯一的元素来更新特定元素中的数据?我不能使用组件的内部状态,因为我需要所选和可拖动元素的总数据:例如,我用ctrl选择了几个元素,当我开始拖动其中一个时,另一个也必须被拖动。
发布于 2022-12-02 23:40:54
要更新数组中特定元素的数据而不重新绘制所有元素,可以结合使用useReducer钩子和useMemo钩子。useReducer钩子允许您定义一个还原器函数,它根据分派的操作更新状态。useMemo钩子允许您计算一个回忆录值,该值只有在某个依赖项发生变化时才会重新计算。
下面是一个示例,说明如何使用useReducer和useMemo挂钩来更新数组中特定元素的数据,而不必重新绘制所有元素:
const [state, dispatch] = useReducer(reducer, initialState);
const data = useMemo(() => {
return state.data.map(item => {
if (item.id === state.selectedId) {
return {
...item,
selected: true
};
} else if (item.id === state.draggingId) {
return {
...item,
dragging: true
};
}
return item;
});
}, [state.data, state.selectedId, state.draggingId]);
const handleDragStart = useCallback((id) => {
dispatch({ type: 'DRAG_START', id });
}, []);
const handleSelect = useCallback((id) => {
dispatch({ type: 'SELECT', id });
}, []);在上面的代码中,我们使用useReducer钩子定义了一个还原器函数。还原器函数接受当前状态和动作,并根据动作返回一个新状态。我们还定义了两个动作创建者,handleDragStart和handleSelect,它们分别分派DRAG_START和选择操作。
接下来,我们使用useMemo钩子来计算数据数组的回传版本。useMemo钩子接受返回要回传的值的函数和依赖项列表。在这种情况下,函数返回更新后的数据数组,并根据当前状态的selectedId和draggingId更新选定的和拖动的元素。
最后,我们使用React组件中的数据数组来呈现元素。由于数据数组是回忆录的,所以只有当状态中的selectedId或draggingId发生变化时,才会重新计算它,这将确保
https://stackoverflow.com/questions/74633288
复制相似问题