嗯,当我想更新一个项目时,我调用UseEffect并对我的endpoint进行异步调用,但我想解决db中不存在id时的问题,它会抛出以下错误:警告:无法对未安装的组件执行React状态更新。这是一个no-op,但它表示应用程序中存在内存泄漏。要修复此问题,请取消useEffect清理函数中的所有订阅和异步任务。
export const AddOrUpdateItem = () => {
const {id} = useParams();
const [itemToUpdate, setItemToUpdate] = useState(null);
const history = useHistory();
useEffect(() => {
if(id) {
const fetchData = async() => {
try {
const resp = await axios.get(`${ITEMS_ENDPOINT}/${id}`);
setItemToUpdate(resp.data);
} catch (error) {
console.log(error);
history.push('/articulos'); //I think here is the problem
}
};
fetchData();
}
}, [id]);
return (
<Box mt={5}>
<Paper elevation={7}>
<Card className="card-root" variant="outlined">
<CardContent>
<h2>{id !== undefined ? 'Actualizar artículo' : 'Registrar artículo'}</h2>
<hr/>
<ItemForm
id={id}
item={itemToUpdate}
/>
</CardContent>
</Card>
</Paper>
</Box>
)
}
最小修复可能如下所示:
useEffect(() => {
const source = axios.CancelToken.source()
if(id) {
const fetchData = async() => {
try {
const resp = await axios.get(`${ITEMS_ENDPOINT}/${id}`, {cancelToken: source.token});
setItemToUpdate(resp.data);
} catch (error) {
console.log(error);
history.push('/articulos');
}
};
fetchData();
}
return ()=> source.cancel() // <<<<<<<<<<<<<<
}, [id]);
使用自定义钩子(Live demo):
import React from "react";
import { useState } from "react";
import {
useAsyncEffect,
CanceledError,
E_REASON_UNMOUNTED
} from "use-async-effect2";
import cpAxios from "cp-axios";
function TestComponent(props) {
const [text, setText] = useState("");
const cancel = useAsyncEffect(
function* () {
setText("fetching...");
try {
const json = (yield cpAxios(props.url).timeout(props.timeout)).data;
setText(`Success: ${JSON.stringify(json)}`);
} catch (err) {
CanceledError.rethrow(err, E_REASON_UNMOUNTED);
setText(err.toString());
}
},
[props.url]
);
return (
<div className="component">
<div>{text}</div>
<button className="btn btn-warning" onClick={cancel}>
Cancel request
</button>
</div>
);
}
使用内部状态的演示(实时演示):
import React from "react";
import { useAsyncEffect } from "use-async-effect2";
import cpAxios from "cp-axios";
function TestComponent(props) {
const [cancel, done, result, err] = useAsyncEffect(
function* () {
return (yield cpAxios(props.url)).data;
},
{ states: true, deps: [props.url] }
);
return (
<div className="component">
<div>
{done ? (err ? err.toString() : JSON.stringify(result)) : "loading..."}
</div>
<button className="btn btn-warning" onClick={cancel} disabled={done}>
Cancel async effect
</button>
</div>
);
}