问题描述
我有一张带有叠加层的地图.我有一个效果,当基础数据发生变化时,删除旧的叠加层并重新绘制一个新的叠加层.
I have a map which has an overlay. I have an effect which, when the underlying data changes, deletes the old overlay and re-draws a new one.
值得注意的是,我正在使用 "react-hooks/exhaustive-deps"
并且它似乎来自 我读到的所有内容 只是删除依赖overlay
不是正确的答案(但它确实有效).
Of note, I'm using "react-hooks/exhaustive-deps"
and it seems from everything I read that just removing the dependency overlay
is not the right answer (but it does work).
注意,data 是传入的 prop.
Of note, data is a prop passed in.
useEffect(() => {
// remove the overlay if it is there,
// I should have overlay as a dependency per exhaustive-reps react eslint rule
if (overlay) map.removeOverlays(overlay);
// Generate the new overlay based on the new data (useCallback function)
const newOverlay = generateNewOverlay(data)
// Store the new overlay so I can remove it later if the data changes
// Doesn't need to be done right away though, just before next render
setOverlay(newOverlay);
// Show the new overlay on my map
map.addOverlays(newOverlay);
}, [map, overlay, data, generateNewOverlay]);
这当然会是一个无限循环,因为我正在设置叠加层并使其成为依赖项.我也不喜欢在效果中立即使用 setState ,因为它会导致另一个渲染.我错过了什么?我如何实现这个逻辑?
This of course will be an infinite loop because I'm setting overlay and making it a dependency. I also don't like using setState immediately in an effect as it causes another render. What am I missing? How do I achieve this logic?
我确实阅读了大约 5 个类似标题的问题,但他们没有回答我的问题.
I did read about 5 similarly titled questions, but they did not answer my question.
类似的问题,但不问而保持详尽的-reps deps lint 规则,这不是'这对他们来说不是一个因素,因为他们在更改状态之前没有读取状态.
Similar question, but not asking while keep exhaustive-reps deps lint rule which isn't a factor for them because they aren't reading the state before changing it.
我仍然遇到 useState 和 reducer 应该是纯的问题.我遇到问题的依赖项 (overlay
) 的目的是我必须检查覆盖是否存在.如果是这样,我需要做一个非纯的事情,即在设置我的新叠加层之前从地图中删除该叠加层.这行代码使它变得不纯:
I still have the problem where useState and a reducer should be pure. The purpose of the dependency I'm having an issue with (overlay
) is that I have to check if overlay exists. If it does, I need to do a non-pure thing which is remove that overlay from the map before setting my new overlay. This line of code is what makes it not pure:
if (overlay) map.removeOverlays(overlay);
如果没有那条线,我的依赖项列表中永远不需要 overlay
并且这整个事情都不会成为一个因素.正如您所看到的,由于该行,接受的答案并不纯粹.
Without that line, I'd never need overlay
in my dependency list and this entire thing wouldn't be a factor. As you can see the accepted answer is not pure because of that line.
useReducer 答案在减速器之外有这一行,所以 overlay
应该是一个依赖项,或者它需要进入减速器.第一个选项是我试图通过 "react-hooks/exhaustive-deps"
避免的,而第二个答案并不纯粹.
The useReducer answer has this line outside the reducer so overlay
should be a dependency or it needs to go in the reducer. The first option is what I'm trying to avoid by the "react-hooks/exhaustive-deps"
and the second answer is not pure.
感谢任何帮助.
最终
我发现解决这个问题的最好方法是正确使用 useEffect 中的清理.我需要状态,以便以后可以从地图中删除内容.
I found the best way to approach this was to use the cleanup in useEffect properly. I was requiring state so that I could remove things from a map later.
useEffect(() => {
// remove the overlay if it is there,
// I originally needed this to store the overlay so I could remove it later, but if I use cleanup properly this isn't needed
// if (overlay) map.removeOverlays(overlay);
// Generate the new overlay based on the new data (useCallback function)
const newOverlay = generateNewOverlay(data)
// Store the new overlay so I can remove it later if the data changes
// Doesn't need to be done right away though, just before next render (This is what a cleanup is!)
// setOverlay(newOverlay);
// Show the new overlay on my map
map.addOverlays(newOverlay);
// New code below
return () => {map.removeOverlays(newOverlay)};
}, [map, data, generateNewOverlay]);
推荐答案
你可以在setOverlay
中使用一个函数:
You can use a function inside of setOverlay
:
useEffect(() => {
setOverlay(prev => {
// remove the overlay if it is there,
// I should have overlay as a dependency per exhaustive-reps react eslint rule
if (prev) map.removeOverlays(prev);
// Generate the new overlay based on the new data (useCallback function)
const newOverlay = generateNewOverlay(data)
// Show the new overlay on my map
map.addOverlays(newOverlay);
return newOverlay;
});
}, [map, data, generateNewOverlay]);
在prev
参数中,您可以获得overlay
的当前状态.这样您就不必将 overlay
状态变量添加到依赖数组中.因此,当 overlay
更新时,效果不会触发.
In the prev
parameter you get the current state of overlay
. This way you don't have to add the overlay
state variable to the dependency array. Hence, the effect won't trigger when overlay
updates.
这篇关于如何读取和修改 useEffect IAW 'exhaustive-deps' lint 规则中的状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!