当我在react功能组件内调用第二个API时,我无法更新状态。第一个API调用在useEffect内部,而第二个API调用在用户单击按钮时完成。完成第二个API调用后,react引发此错误“无法在已卸载的组件上执行React状态更新。这是一个空操作,但表明您的应用程序中存在内存泄漏。要修复,取消所有订阅并进行异步useEffect清理功能中的任务”。 而且状态没有更新,我想在第二次API调用后设置状态。该如何解决?
我的代码:
const AddNewProduct = () => {
const [productName, setProductName] = useState("");
const [originalPrice, setOriginalPrice] = useState("");
const [newPrice, setNewPrice] = useState("");
const [category, setCategory] = useState("");
const [description, setDescription] = useState("");
const [categoriesArray, setCategoriesArray] = useState([]);
const [isLogin, setIsLogin] = useState([]);
const [id, setId] = useState("");
useEffect(() => {
const getCategoriesData = async () => {
const Data = await fetchCategoriesApi();
setIsLogin(Data.data.login);
setCategoriesArray(Data.data.data);
console.log(Data);
};
getCategoriesData();
}, []);
const handleCategoryClick = (id) => {
setCategory(id);
console.log(id);
};
const handleNextClick = async () => {
const postApi = "https://fliqapp.xyz/api/seller/products";
try {
const post = await axios
.post(
postApi,
{
product_name: productName,
product_desc: description,
product_price: originalPrice,
product_cat: category,
},
{
headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`,
},
}
)
.then((response) => {
setId(response.data.data.product_id);
console.log(id);
console.log(response);
});
} catch (error) {
return error;
}
console.log("clicked");
};
return (
<>
<div className={styles.container}>
<div className={styles.blank}></div>
<input
type="text"
className={styles.input_field}
placeholder="Product name*"
onChange={(e) => setProductName(e.target.value)}
/>
<input
type="text"
className={styles.input_field}
placeholder="original price*"
onChange={(e) => setOriginalPrice(e.target.value)}
/>
<input
type="text"
className={styles.input_field}
placeholder="new price"
onChange={(e) => setNewPrice(e.target.value)}
/>
<select
name="parent category"
id="parentcategory"
className={styles.dropdown}
defaultValue={"DEFAULT"}
onChange={(e) => handleCategoryClick(e.target.value)}
>
<option value="DEFAULT" disabled>
select category
</option>
{isLogin &&
categoriesArray.map((item, index) => (
<option value={item.id} key={index}>
{item.cat_name}
</option>
))}
</select>
<textarea
type="textarea"
className={styles.input_field}
placeholder="Description"
rows="4"
onChange={(e) => setDescription(e.target.value)}
/>
<Link
to={{
pathname: `/add_image/${id}`,
}}
className={styles.btn}
onClick={handleNextClick}
disabled
>
Next
</Link>
<div className={styles.header}>
<h1 className={styles.heading_normal}>Add new product</h1>
</div>
</div>
</>
);
};
答案 0 :(得分:1)
您需要将Link
更改为Button
并手动导航到其他路由,因为路由id
中使用的/add_image/${id}
来自第二次Api呼叫。
原因:因为当您单击“链接”时,它将触发axios请求并更改您的应用程序的路由,因此将卸载当前组件,并安装新的路由组件,在这种情况发生后,您的axios响应会重新出现并尝试
setState
在未安装的组件上。
// import
import { useHistory } from 'react-router-dom';
// inside component
const history = useHistory();
// click handler
const handleNextClick = async () => {
// ...axiosrequest
.then((response) => {
setId(response.data.data.product_id); // may be not needed now
const id = response.data.data.product_id;
history.push(`/add_image/${id}`);
}
}
// button
<button
className={styles.btn}
onClick={handleNextClick}
>
Next
</button>
通过这种方式,只有在收到服务器的正确响应后,才更改路由一次,并且根据response ID
更新路由。
为了获得更好的用户体验,您可以在执行axios ajax请求的同时显示加载情况。
如有疑问,请发表评论。