[英]How do i properly use useEffect for a async fetch call with react? react-hooks/exhaustive-deps
Hi i'm facing a problem with the useEffect
hook in React.嗨,我在 React 中遇到了
useEffect
钩子的问题。 The code below works like it should but es-lint suggests that i need to provide dependencies in the dependency array from the useEffect
.下面的代码可以正常工作,但 es-lint 建议我需要在
useEffect
的依赖数组中提供依赖项。
// eslint-disable-next-line react-hooks/exhaustive-deps
// eslint-disable-next-line react-hooks/exhaustive-deps
工作代码export default function UsersList() {
const [users, setUsers] = useState<User[]>([]);
const { setError } = useContext(errorContext);
const { isLoading, setIsLoading } = useContext(globalContext);
useEffect(() => {
if (users.length < 1) {
fetchUsers();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
async function fetchUsers () {
try {
setIsLoading(true);
const fetchedUsers = await api.getUsers();
setUsers(fetchedUsers);
} catch (error) {
setError(error);
} finally {
setIsLoading(false);
}
}
}
i tried to write it like this the code triggers a infinite loop.. (because the states get constantly changed inside the function and triggers the useEffect
every time because of the declared dependencies)我试着这样写代码触发了一个无限循环..(因为状态在 function 内不断变化,并且由于声明的依赖关系每次都会触发
useEffect
)
useEffect(() => {
async function fetchUsers () {
try {
setIsLoading(true);
const fetchedUsers = await api.getUsers();
setUsers(fetchedUsers);
} catch (error) {
setError(error);
} finally {
setIsLoading(false);
}
}
if (users.length < 1) {
fetchUsers();
}
}, [setIsLoading, setError, users]);
i also tried putting the fetchUsers()
inside the dependencies array but this had no effect.我还尝试将
fetchUsers()
放在依赖项数组中,但这没有效果。
How do i properly set up a async call when the component mounts without having to use // eslint-disable-next-line react-hooks/exhaustive-deps
?我如何在组件安装时正确设置异步调用而不必使用
// eslint-disable-next-line react-hooks/exhaustive-deps
?
Your fetchUsers
function is recreating itself with every render triggering use effect.您的
fetchUsers
function 正在通过每个渲染触发使用效果重新创建自己。 You have to keep its reference the same across renders by wrapping it with useCallback
, see https://reactjs.org/docs/hooks-reference.html#usecallback您必须通过使用
useCallback
将其包装在渲染中保持其引用相同,请参阅https://reactjs.org/docs/hooks-reference.html#usecallback
Furthermore, to ensure that we call this useEffect only once (when the first render occurs) we can use useRef to store a boolean value which will prevent useEffect from infinite loop此外,为了确保我们只调用这个 useEffect 一次(当第一次渲染发生时),我们可以使用 useRef 来存储一个 boolean 值,这将防止 useEffect 无限循环
export default function UsersList() {
const [users, setUsers] = useState<User[]>([]);
const { setError } = useContext(errorContext);
const { isLoading, setIsLoading } = useContext(globalContext);
const fetchUsers = useCallback(async function () {
try {
setIsLoading(true);
const fetchedUsers = await api.getUsers();
setUsers(fetchedUsers);
} catch (error) {
setError(error);
} finally {
setIsLoading(false);
}
}, [setIsLoading, setUsers, setError]);
// Added a ref here to ensure that we call this function only once in initial render
// If you need to refetch the users on error, just call fetchUsers
const isFetchedRef = useRef(false);
useEffect(() => {
if (!isFetchedRef.current) {
isFetchedRef.current = true;
fetchUsers();
}
}, [isLoading, fetchUsers]);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.