I have this custom hook to fetch my data but i have problem its fetch only once on render i know its becouse array on use effect its empty but when put there setPartData and url or data.data it becomes like infinite loop how to avoid this.
How to achive its refetch every time when data is change without burining my computer CPU.
import React, { useState, useEffect } from "react";
export const apiStates = {
LOADING: "LOADING",
SUCCESS: "SUCCESS",
ERROR: "ERROR",
};
export const useApi = (url) => {
const [data, setData] = useState({
state: apiStates.LOADING,
error: "",
data: [],
});
const setPartData = (partialData) => setData({ ...data, ...partialData });
useEffect(() => {
setPartData({
state: apiStates.LOADING,
});
fetch(url)
.then((response) => response.json())
.then((data) => {
setPartData({
state: apiStates.SUCCESS,
data,
});
})
.catch(() => {
setPartData({
state: apiStates.ERROR,
error: "fetch failed",
});
});
}, []);
return data;
};
And component where i use it
const { state, error, data } = useApi("http://localhost:5000/api/v1/albums");
const albums = data.data;
switch (state) {
case apiStates.ERROR:
return <ErrorMessage>{error || "General error"}</ErrorMessage>;
case apiStates.SUCCESS:
return (
<CartWrapper>
{albums.length > 0 ? (
albums.map((album) => (
<CardWithEdit
width={"23rem"}
height="16rem"
color={album.color}
bckImg={album.bckImgUrl}
key={album._id}
link={`/albums/${album._id}`}
editLink={`edit/${album._id}`}
id={album._id}
>
{album.name}
</CardWithEdit>
))
) : (
<h1>No albums yet</h1>
)}
</CartWrapper>
);
default:
return <Loader />;
}
Delete where i need to reload page to get updated state
const CardWithEdit = ({
width,
height,
bckImg,
color,
children,
link,
editLink,
id,
}) => {
const [state, setState] = useState(false);
const handleClick = () => setState(!state);
const handleDelete = async () => {
await fetch(`http://localhost:5000/api/v1/albums/${id}`, {
method: "DELETE",
});
handleClick();
};
return (
<Card width={width} height={height} bckImg={bckImg}>
<AlbumtTitle color={color}>{children}</AlbumtTitle>
<LinkButton background={color} to={link}>
See more
</LinkButton>
<IconWrapper>
<div>
<Link to={editLink}>
<AiOutlineEdit />
</Link>
</div>
<div onClick={handleClick}>
<AiOutlineDelete
style={{
cursor: "pointer",
}}
/>
</div>
</IconWrapper>
{state && (
<Dialog
handleClick={handleClick}
handleDelete={handleDelete}
deleteText={"Delete"}
/>
)}
</Card>
);
};
You need to use another state variable, where you can store the recently deleted element ID. The useEffect will have to be hooked to that variable. If that ID, changes, the useEffect will fetch new data.
const [deleteID, setDeleteID] = useState(null); //update this in the delete component
useEffect(() => {
setPartData({
state: apiStates.LOADING,
});
fetch(url)
.then((response) => response.json())
.then((data) => {
setPartData({
state: apiStates.SUCCESS,
data,
});
})
.catch(() => {
setPartData({
state: apiStates.ERROR,
error: "fetch failed",
});
});
}, [deleteID]); //useEffect will only fire when delete ID changes.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.