我有一张地图,上面有一个叠加层。我有一个效果,当基础数据发生变化时,删除旧的覆盖层并重新绘制一个新的覆盖层。
值得注意的是,我正在使用"react-hooks/exhaustive-deps"
,并且从我读到的所有内容看来,仅仅删除依赖项overlay
并不是正确的答案(但它确实有效)。
值得注意的是,数据是传入的props。
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,因为它会导致另一个渲染。我错过了什么?我如何实现这个逻辑?
我确实阅读了大约 5 个类似标题的问题,但他们没有回答我的问题。
类似的问题,但不问而保持详尽的代表 deps lint 规则,这对他们来说不是一个因素,因为他们在更改状态之前没有读取状态。
编辑:
我仍然遇到 useState 和 reducer 应该是纯的问题。我对 ( overlay
)有问题的依赖项的目的是我必须检查是否存在叠加层。如果是这样,我需要做一个非纯的事情,即在设置我的新叠加层之前从地图中删除该叠加层。这行代码使它不纯:
if (overlay) map.removeOverlays(overlay);
如果没有那条线,我就永远不需要overlay
在我的依赖项列表中,这整个事情都不会成为一个因素。正如您所看到的,由于那条线,接受的答案并不纯粹。
useReducer 答案在减速器之外有这一行,所以overlay
应该是一个依赖项,或者它需要进入减速器。第一个选项是我试图避免的"react-hooks/exhaustive-deps"
,第二个答案不纯。
感谢任何帮助。
最终编辑:
我发现解决这个问题的最好方法是正确使用 useEffect 中的清理。我需要状态,以便稍后可以从地图中删除内容。
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]);