我正在使用钩子useEffect向我的服务器发出获取请求,并且不断收到此警告:
警告:无法对未挂载的组件执行 React 状态更新。这是无操作,但它表示应用程序中存在内存泄漏。若要解决此问题,请取消 useEffect 清理函数中的所有订阅和异步任务。
我了解此警告的原因,但如何清理它?我尝试了本文中建议的方法,但没有运气:https://dev.to/pallymore/clean-up-async-requests-in-useeffect-hooks-90h
这是我的代码:
import React, { useEffect, useState } from 'react';
import { Redirect, Route } from 'react-router-dom';
export default function ProtectedRoute({ component: Component, ...rest }) {
const [ user, setUser ] = useState('');
useEffect(() => {
const fetchUser = async () => {
try {
const response = await fetch('http://localhost:5000/user', {
credentials: 'include'
});
const data = await response.json();
setUser(data.session.passport.user);
} catch (error) {
console.log(error);
}
}
fetchUser();
return () => {
// Do some cleanup
}
}, [])
return (
<Route { ...rest } render={ () => user ? <Component /> : <Redirect to="/login" /> }/>
)
}
任何帮助都值得赞赏:)
更新:感谢Tony Nguyen下面的解决方案,这是我的工作代码:
import React, { useEffect, useState } from 'react';
import { Redirect, Route } from 'react-router-dom';
import Loading from './Loading';
import Error from './Error';
export default function ProtectedRoute({ component: Component, ...rest }) {
const [ user, setUser ] = useState('');
const [ fetchingUser, setFetchingUser ] = useState(true);
const [ noError, setNoError ] = useState(true);
useEffect(() => {
const fetchUser = async () => {
try {
const response = await fetch('http://localhost:5000/user', {
credentials: 'include'
});
if (fetchingUser) {
const data = await response.json();
setUser(data.session.passport.user);
}
setFetchingUser(false);
} catch {
setNoError(false);
}
}
fetchUser();
}, [])
return (
<div>
<Route { ...rest } render={ () => { if (!noError) return <Error />} }/>
<Route { ...rest } render={ () => { if (fetchingUser && noError) return <Loading />} }/>
<Route { ...rest } render={ () => { if (user && !fetchingUser && noError) return <Component />} }/>
<Route { ...rest } render={ () => { if (!user && !fetchingUser && noError) return <Redirect to="/login" />} }/>
</div>
)
}
你的第一段代码没问题,只需要一些修改,添加fetchingUser
让组件知道你正在获取用户,不要重定向
import React, { useEffect, useState } from 'react';
import { Redirect, Route } from 'react-router-dom';
export default function ProtectedRoute({ component: Component, ...rest }) {
// add fetchingUser state with defaut is true
const [ fetchingUser, setFetchingUser ] = useState(true);
const [ user, setUser ] = useState('');
useEffect(() => {
const fetchUser = async () => {
try {
const response = await fetch('http://localhost:5000/user', {
credentials: 'include'
});
const data = await response.json();
setUser(data.session.passport.user);
// setFetching is false here
setFetchingUser(false)
} catch (error) {
// You can create an error state and set error here
console.log(error);
}
}
fetchUser();
return () => {
// Do some cleanup
}
}, [])
// add fetchingUser into conditions
// You can do better job that is if fetching show Loading component
// If error show error component
// if not fetching not error and have user show user component
// if not fetching not error and not user redirect to login
return (
<Route { ...rest } render={ () => user && !fetchingUser ? <Component /> : <Redirect to="/login" /> }/>
)
}
这是对我有用的: 链接到文章
请按照以下代码中的步骤#1至#3进行操作:
const [isFetching, setIsFetching] = useState(false);
useEffect(() => {
if (user.address && user.token) {
setIsFetching(true);
// STEP #1
const abortController = new AbortController();
(async function fetchWalletInfo() {
try {
const response = await fetch(`${process.env.NEXT_PUBLIC_WEB_API}/wallet-info`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
address: user.address,
token: user.token,
}),
// STEP #2
signal: abortController.signal,
});
setIsFetching(false);
if (response.status == 200) {
const { balance } = await response.json();
setWallet({ balance });
} else {
alert(await response.json());
}
} catch (error) {
console.log(error);
}
})();
// STEP #3
return () => abortController.abort();
}
}, [user.address, user.token]);