Reactjs Can';t在未安装的组件上执行React状态更新。React、redux和useEffect存在问题
我有一个使用如下钩子的React组件:Reactjs Can';t在未安装的组件上执行React状态更新。React、redux和useEffect存在问题,reactjs,redux,react-redux,axios,react-hooks,Reactjs,Redux,React Redux,Axios,React Hooks,我有一个使用如下钩子的React组件: const myComponent = (props) => { useEffect(() => { FetchData() .then(data => { setState({data: data}); } // some other code }, []); //some other code and render method... } fetchData负责使用axi
const myComponent = (props) => {
useEffect(() => {
FetchData()
.then(data => {
setState({data: data});
}
// some other code
}, []);
//some other code and render method...
}
fetchData负责使用axios并从API获取数据:
const FetchData = async () => {
try {
res = await myApiClient.get('/myEndpoint);
} catch (err) {
console.log('error in FetchData');
res = err.response
}
}
最后,myApiClient是外部定义的。为了能够使用不同的API,我不得不使用这个设置
import axios from "axios";
axios.defaults.headers.post["Content-Type"] = "application/json";
const myApiClient = axios.create({
baseURL: process.env.REACT_APP_API1_BASEURL
});
const anotherApiClient = axios.create({
baseURL: process.env.REACT_APP_API2_BASEURL
});
export {
myApiClient,
anotherApiClient
};
通过这种设置,我得到了警告
Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
我在谷歌上搜索了一下,看到了一些关于如何清理useEffect请求的建议,比如,但我的axios是外部定义的。那么,如何使用此设置发送取消
此外,应用程序正在使用redux,不确定是否以某种方式涉及到它
欢迎任何其他避免错误的建议。您可以使用
rxjs
中的defer
来实现以下目的:
const FetchData = () => {
try {
return myApiClient.get("/myEndpoint");
} catch (err) {
console.log("error in FetchData");
return err.response;
}
};
const myComponent = (props) => {
useEffect(() => {
const subscription = defer(FetchData()).subscribe({
next: ({
data
}) => {
setState({
data: data
});
},
error: () => {
// error handling
},
complete: () => {
// cancel loading state etc
}
});
return () => subscription.unsubscribe();
}, []);
}
始终检查您是否正在处理fetch或任何长操作
let _isMounted = false;
const HooksFunction = props => {
const [data, setData] = useState({}); // data supposed to be object
const fetchData = async ()=> {
const res = await myApiClient.get('/myEndpoint');
if(_isMounted) setData(res.data); // res.data supposed to return an object
}
useEffect(()=> {
_isMounted = true;
return ()=> {
_isMounted = false;
}
},[]);
return (
<div>
{/*....*/}
<div/>
);
}
let _isMounted=false;
const HooksFunction=props=>{
const[data,setData]=useState({});//应该是对象的数据
const fetchData=async()=>{
const res=await myApiClient.get('/myEndpoint');
if(_isMounted)setData(res.data);//res.data应该返回一个对象
}
useffect(()=>{
_isMounted=真;
return()=>{
_isMounted=错误;
}
},[]);
返回(
{/*....*/}
);
}
你说的“外部”是什么意思?您可以传递到axios请求,并在必要时取消它。我的意思是,我不知道如何将MyApicClient中定义的cancellationToken一直传递到组件中的useEffect。我可以先导出它,然后再导入吗?问题是由Redux Store引起的。这里的解决方案:在项目中使用rxjs
不是一个好主意,如果因为它的大小而没有在其他任何地方使用它,我想你可以单独导入defer
,并利用树抖动来不包括整个库。如果我不够清楚,很抱歉。FetchData位于另一个文件中,并从组件中的useEffect导出以供使用。感谢不管是否导出,您只需检查是否(\u isMounted)
然后更新状态。