reactjs - 如何在 useEffect IAW 'exhaustive-deps' lint 规则中读取和修改状态
问题描述
我有一张有叠加层的地图。我有一个效果,当基础数据发生变化时,删除旧的叠加层并重新绘制一个新的叠加层。
值得注意的是,我正在使用,从我读到"react-hooks/exhaustive-deps"
的所有内容看来,仅仅删除依赖项并不是正确的答案(但它确实有效)。overlay
值得注意的是,数据是传入的道具。
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]);
解决方案
我认为这里的问题是您适应此 linter 规则的方法过于被动。您在useEffect
任何时候运行回调中的所有代码,但您真的只想在data
更改时执行这些代码。
因此,您可以在代码中反映这一点:
const [shouldUpdateOverlay, setShouldUpdateOverlay] = useState(false);
useEffect(() => {
if (shouldUpdateOverlay) {
// 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);
// Show the new overlay on my map
map.addOverlays(newOverlay);
// 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);
setShouldUpdateOverlay(false);
}
}, [map, overlay, shouldUpdateOverlay data, generateNewOverlay]);
// use from event handlers, etc.
const updateData = (newData) => {
setData(newData);
setShouldUpdateOverlay(true);
};
实际上,这是一种过度劳累的方法来完成您可以通过将[data]
作为唯一依赖项来实现的相同的事情useEffect
,因为这确实是唯一重要的依赖项。但是,我相信以上内容应该可以让您在不违反 linter 规则的情况下实现您想要做的事情。
推荐阅读
- visual-studio-code - 如何触发激活 vscode markdown 扩展
- firebase - 托管 React Native 的 Firebase - 如何设置我的项目的一部分在主域上,一部分在子域上?
- php - 如何使用购物车总数来更改 WooCommerce 中的购物车商品价格
- python - 石墨烯 Python 变异列表输入
- javascript - 为什么 NetworkInformation.effectiveType 给我返回的是 4g 网络而不是 wifi?
- javascript - 如何根据 *ngIf 更改按钮状态
- tensorflow - 如何训练模型以识别放大或部分对象图像的对象?
- java - 如何在 JAVA 中使用 3 个实体之间的乐观锁定
- yocto - 是否有 DISTRO_FEATURES_append 的可用列表?
- python - 在本地运行 AWS SageMaker 线性学习器时角色名称验证错误