在使用React 16.8.6(以前的版本在16.8.3上很好)时,我尝试阻止获取请求中的无限循环时出现此错误
./src/components/BusinessesList.js
Line 51: React Hook useEffect has a missing dependency: 'fetchBusinesses'.
Either include it or remove the dependency array react-hooks/exhaustive-deps
我一直找不到能够很好地阻止无限循环的解决方案。我想远离使用useReducer()
。我确实在的讨论中找到了You can always // eslint-disable-next-line react-hooks/exhaustive-deps if you think you know what you're doing.
的可能解决方案,但我对正在做的事情没有把握,所以我还没有尝试实现它。
我具有当前的设置https://github.com/facebook/react/issues/14920,唯一的评论是关于useCallback()
的我不熟悉。
我目前如何使用useEffect()
(与componentDidMount()
类似,我一开始只想运行一次)
useEffect(() => {
fetchBusinesses();
}, []);
const fetchBusinesses = () => {
return fetch("theURL", {method: "GET"}
)
.then(res => normalizeResponseErrors(res))
.then(res => {
return res.json();
})
.then(rcvdBusinesses => {
// some stuff
})
.catch(err => {
// some error handling
});
};
答案 0 :(得分:150)
您可以将其直接设置为useEffect
回调:
useEffect(fetchBusinesses, [])
它将仅触发一次,因此请确保正确设置了所有函数的依赖项(与使用componentDidMount/componentWillMount...
相同)
编辑02/21/2020
只是为了完整性:
useEffect
回调(如上所述)useEffect(fetchBusinesses, [])
useEffect()
内声明函数useEffect(() => {
function fetchBusinesses() {
...
}
fetchBusinesses()
}, [])
useCallback()
在这种情况下,如果函数中具有依赖项,则必须将它们包含在useCallback
依赖项数组中,如果函数的参数发生更改,这将再次触发useEffect
。除此之外,还有很多样板...因此只需像useEffect
一样直接将函数传递给1. useEffect(fetchBusinesses, [])
。
const fetchBusinesses = useCallback(() => {
...
}, [])
useEffect(() => {
fetchBusinesses()
}, [fetchBusinesses])
useEffect(() => {
fetchBusinesses()
}, []) // eslint-disable-line react-hooks/exhaustive-deps
答案 1 :(得分:5)
如果除了效果之外没有在其他地方使用fetchBusinesses方法,则可以将其移至效果中并避免出现警告
useEffect(() => {
const fetchBusinesses = () => {
return fetch("theURL", {method: "GET"}
)
.then(res => normalizeResponseErrors(res))
.then(res => {
return res.json();
})
.then(rcvdBusinesses => {
// some stuff
})
.catch(err => {
// some error handling
});
};
fetchBusinesses();
}, []);
但是,如果您在渲染之外使用fetchBusinesses,则必须注意两点
fetchBusinesses
作为方法,并且在挂载过程中使用它的封闭方式,将不会有任何问题。总结起来,我想说的是,如果您在fetchBusinesses
之外使用useEffect
,则可以使用// eslint-disable-next-line react-hooks/exhaustive-deps
禁用规则,否则可以将方法移到useEffect内
答案 2 :(得分:3)
只需将函数作为参数传递给useEffect数组...
useEffect(() => {
functionName()
}, [functionName])
答案 3 :(得分:3)
const [mount, setMount] = useState(false)
const fetchBusinesses = () => {
//function defination
}
useEffect(() => {
if(!mount) {
setMount(true);
fetchBusinesses();
}
},[fetchBusinesses]);
这是非常简单的解决方案,您无需覆盖es-lint警告。只需维护一个标志来检查组件是否已安装。
答案 4 :(得分:2)
./src/components/BusinessesList.js
Line 51: React Hook useEffect has a missing dependency: 'fetchBusinesses'.
Either include it or remove the dependency array react-hooks/exhaustive-deps
不是JS / React错误,而是警告警告。
这是在告诉您钩子取决于函数fetchBusinesses
,因此您应将其作为依赖项传递。
useEffect(() => {
fetchBusinesses();
}, [fetchBusinesses]);
如果fetchBusinessess
不在运行中,则不会真正改变任何东西,但是警告会消失。
答案 5 :(得分:2)
您尝试这种方式
const fetchBusinesses = () => {
return fetch("theURL", {method: "GET"}
)
.then(res => normalizeResponseErrors(res))
.then(res => {
return res.json();
})
.then(rcvdBusinesses => {
// some stuff
})
.catch(err => {
// some error handling
});
};
和
useEffect(() => {
fetchBusinesses();
});
为您服务。 但是我的建议是尝试这种方式也对您有用。 比以前更好。我使用这种方式:
useEffect(() => {
const fetchBusinesses = () => {
return fetch("theURL", {method: "GET"}
)
.then(res => normalizeResponseErrors(res))
.then(res => {
return res.json();
})
.then(rcvdBusinesses => {
// some stuff
})
.catch(err => {
// some error handling
});
};
fetchBusinesses();
}, []);
如果您基于特定ID获得数据,则添加回调useEffect [id]
,然后无法向您显示警告
React Hook useEffect has a missing dependency: 'any thing'. Either include it or remove the dependency array
答案 6 :(得分:1)
就我而言,它对我的局部变量 organization
有此警告,当我将 organization
放入依赖数组 useEffect
时,它会无限获取。因此,如果您有一些像我这样的问题,请使用 useEffect
与依赖数组和拆分:
因为如果你有多个修改状态的api调用,它会多次调用useEffect
来自:
const { organization } = useSelector(withOrganization)
const dispatch = useDispatch()
useEffect(() => {
dispatch(getOrganization({}))
dispatch(getSettings({}))
dispatch(getMembers({}))
}, [dispatch, organization])
致:
const { organization } = useSelector(withOrganization)
const dispatch = useDispatch()
useEffect(() => {
dispatch(getOrganization({}))
dispatch(getSettings({}))
}, [dispatch, organization])
useEffect(() => {
dispatch(getMembers({}))
}, [dispatch])
答案 7 :(得分:1)
如果您在 useEffect
内部使用的变量在组件内部定义或作为 prop 传递给组件,则会发生此警告。由于您在同一组件内定义了 fetchBusinesses()
,因此您必须将其传递给依赖项数组。
但是如果您导入 fetchBusinesses()
然后在 useEffect
中使用它,则不需要将其添加到依赖项数组中。这就是我们实际设置 redux 应用程序的方式:我们总是导入我们的 action creators 并在 useEffect
中运行它,而不将它添加到依赖项数组中。
useMemo
也是如此。
答案 8 :(得分:1)
我只想像[
一样先开始运行[fetchBusinesses
componentDidMount()
您可以将fetchBusinesses
完全拉出组件:
const fetchBusinesses = () => { // or pass some additional input from component as args
return fetch("theURL", { method: "GET" }).then(n => process(n));
};
const Comp = () => {
React.useEffect(() => {
fetchBusinesses().then(someVal => {
// ... do something with someVal
});
}, []); // eslint warning solved!
return <div>{state}</div>;
};
这不仅可以提供简单的解决方案,而且可以解决详尽的下降警告。 fetchBusiness
现在可以更好地测试,并且可以简化Comp
,因为它位于React树之外的模块范围内。
在外部将fetchBusinesses
移到这里可以很好地工作,因为由于陈旧的闭包范围([]
dep,我们只能从组件中读取 initial 道具和状态。在useEffect
中。
useEffect
依赖于此值(纯计算函数)useCallback
作为最后包装方法将fetchBusinesses
拉入useEffect()
并不能真正帮助您,如果您访问其中的其他状态。埃斯林特仍然会抱怨:Codesandbox。
我也将避免eslint详尽的说明而忽略评论。在对依赖项进行一些重构和大修时,很容易忘记它们。
答案 9 :(得分:1)
这些警告对于查找不一致更新的组件非常有用:https://reactjs.org/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of-dependencies。
但是,如果要删除整个项目中的警告,可以将其添加到eslint配置中:
{
"plugins": ["react-hooks"],
"rules": {
"react-hooks/exhaustive-deps": 0
}
}
答案 10 :(得分:1)
该解决方案也是由react提供的,他们建议您使用useCallback
,这将返回函数的备忘版本:
'fetchBusinesses'函数使useEffect Hook(在第NN行)的依赖关系在每个渲染上都改变。要解决此问题,请将“ fetchBusinesses”定义包装到其自己的useCallback()中。Hook react-hooks / exhaustive-deps
useCallback
使用简便,因为它与useEffect
具有相同的签名,不同之处在于useCallback返回一个函数。
看起来像这样:
const fetchBusinesses = useCallback( () => {
return fetch("theURL", {method: "GET"}
)
.then(// some stuff)
.catch(// some error handling)
}, [//deps])
// We have a first effect thant uses fetchBusinesses
useEffect(() => {
// do things and then fetchBusinesses
fetchBusinesses();
}, [fetchBusinesses]);
// We can have many effect thant uses fetchBusinesses
useEffect(() => {
// do other things and then fetchBusinesses
fetchBusinesses();
}, [fetchBusinesses]);
答案 11 :(得分:0)
实际上,当您使用钩子进行开发时,警告非常有用。但在某些情况下,它可能会刺穿您。尤其是当您不需要监听依赖项更改时。
如果您不想将fetchBusinesses
放入钩子的依赖项中,则可以简单地将其作为参数传递给钩子的回调,并像这样将主fetchBusinesses
设置为其默认值
useEffect((fetchBusinesses = fetchBusinesses) => {
fetchBusinesses();
}, []);
这不是最佳实践,但在某些情况下可能会有用。
也如Shubnam所写,您可以添加以下代码以告诉ESLint忽略对钩子的检查。
// eslint-disable-next-line react-hooks/exhaustive-deps
答案 12 :(得分:0)
您可以删除第二个参数类型数组[]
,但是fetchBusinesses()
也将在每次更新时被调用。您可以根据需要将IF
语句添加到fetchBusinesses()
实现中。
React.useEffect(() => {
fetchBusinesses();
});
另一种方法是在组件外部实现fetchBusinesses()
函数。只是不要忘记将任何依赖项参数传递给您的fetchBusinesses(dependency)
调用(如果有)。
function fetchBusinesses (fetch) {
return fetch("theURL", { method: "GET" })
.then(res => normalizeResponseErrors(res))
.then(res => res.json())
.then(rcvdBusinesses => {
// some stuff
})
.catch(err => {
// some error handling
});
}
function YourComponent (props) {
const { fetch } = props;
React.useEffect(() => {
fetchBusinesses(fetch);
}, [fetch]);
// ...
}
答案 13 :(得分:0)
好吧,如果您想换个角度看,您只需要知道React具有非exhaustive-deps
的选项是什么?您不应该在效果内使用闭包函数的原因之一是在每个渲染上,它将再次被重新创建/破坏。
因此,钩子中有多个React方法被认为是稳定且不会耗尽的,您无需将它们应用于useEffect
依赖项,从而不会破坏react-hooks/exhaustive-deps
的规则参与。例如,第二个返回变量useReducer
或useState
是一个函数。
const [,dispatch] = useReducer(reducer, {});
useEffect(() => {
dispatch(); // non-exhausted, eslint won't nag about this
}, []);
因此,您可以将所有外部依赖项与当前依赖项一起共存于化简函数中。
const [,dispatch] = useReducer((current, update) => {
const { foobar } = update;
// logic
return { ...current, ...update };
}), {});
const [foobar, setFoobar] = useState(false);
useEffect(() => {
dispatch({ foobar }); // non-exhausted `dispatch` function
}, [foobar]);
答案 14 :(得分:0)
本文是使用钩子获取数据的不错的入门:https://www.robinwieruch.de/react-hooks-fetch-data/
本质上,请在useEffect
中包含提取功能定义:
useEffect(() => {
const fetchBusinesses = () => {
return fetch("theUrl"...
// ...your fetch implementation
);
}
fetchBusinesses();
}, []);
答案 15 :(得分:-1)
仅在下一行禁用eslint;
useEffect(() => {
fetchBusinesses();
// eslint-disable-next-line
}, [fetchBusinesses]);
答案 16 :(得分:-3)
在文件顶部添加此评论以禁用警告。
/* eslint-disable react-hooks/exhaustive-deps */