如何消除React自定义useUserCollection Hook的useEffect依赖警告?
解决自定义Hook中useEffect的依赖项警告
你遇到的警告是因为ESLint的react-hooks/exhaustive-deps规则检测到:你的useEffect内部调用了loadUsers函数,但该函数没有被加入到依赖数组中。但直接把loadUsers加进依赖数组又会引发新问题——因为loadUsers是每次组件渲染都会重新创建的函数,这会导致useEffect在每次渲染时都执行,违背了你“仅在filter变化时执行逻辑”的需求。
下面提供两种可行的解决方式:
方式一:用useCallback包裹loadUsers
通过useCallback缓存loadUsers函数,让它仅在filter变化时才重新生成。这样将loadUsers加入依赖数组后,只有filter改变时才会触发useEffect,既满足规则要求,又符合业务逻辑:
import React from "react"; export const useUserCollection = () => { const [filter, setFilter] = React.useState(""); const [userCollection, setUserCollection] = React.useState([]); // 用useCallback缓存函数,依赖filter const loadUsers = React.useCallback(() => { fetch(`https://jsonplaceholder.typicode.com/users?name_like=${filter}`) .then(response => response.json()) .then(json => setUserCollection(json)); }, [filter]); React.useEffect(() => { loadUsers(); }, [loadUsers]); // 现在依赖缓存后的loadUsers return {userCollection, loadUsers, filter, setFilter}; } export default function App () { const {userCollection, filter, setFilter} = useUserCollection(); return ( <div> <input value={filter} onChange={e => setFilter(e.target.value)} /> <ul> {userCollection.map((user, index) => ( <li key={index}>{user.name}</li> ))} </ul> </div> ); };
方式二:将请求逻辑内联到useEffect中
如果不需要对外暴露loadUsers函数(或者即使暴露,也可以把核心逻辑内联),直接把fetch逻辑写到useEffect内部,这样依赖数组只需要保留filter,完全避开函数依赖的问题:
import React from "react"; export const useUserCollection = () => { const [filter, setFilter] = React.useState(""); const [userCollection, setUserCollection] = React.useState([]); const loadUsers = () => { fetch(`https://jsonplaceholder.typicode.com/users?name_like=${filter}`) .then(response => response.json()) .then(json => setUserCollection(json)); }; React.useEffect(() => { // 直接执行请求逻辑 fetch(`https://jsonplaceholder.typicode.com/users?name_like=${filter}`) .then(response => response.json()) .then(json => setUserCollection(json)); }, [filter]); // 仅依赖filter return {userCollection, loadUsers, filter, setFilter}; } export default function App () { const {userCollection, filter, setFilter} = useUserCollection(); return ( <div> <input value={filter} onChange={e => setFilter(e.target.value)} /> <ul> {userCollection.map((user, index) => ( <li key={index}>{user.name}</li> ))} </ul> </div> ); };
两种方式都能消除警告,同时保证仅在filter变化时执行请求逻辑。如果需要保留loadUsers供外部调用,推荐第一种方式;如果loadUsers只是内部逻辑的封装,第二种方式更简洁。
内容的提问来源于stack exchange,提问作者Vibhu Bajaj
相关产品推荐
相关产品推荐

