I have a React component that I created called List that contains an array of data. I then created a second component that is a filtered version of the list called favoriteList. The component filtering appears to work but there is an issue with the rendering, which causes the component to re-render over and over, and go back and forth between filtered and un-filtered. This results in multiple "too many requests" errors. Here is my code for the favoriteList. It's probably something I am doing wrong in the useEffect
but I can't figure it out. I haven't disabled strict mode as I'm not sure if I should do this.
Update
I removed cards from the dependency array, but the FavoriteHikes component still renders once (as it should with the filtered data) and then renders once more back to the original List. I'm pretty sure it has something to do with setCards being passed to List.
import List from "../List/List"
import "./FavoriteHikes.css"
import { Hike } from "../../Type"
import { useEffect, useState } from "react";
export default function FavoriteHikes () {
const [cards, setCards] = useState<Hike[]>( [] )
useEffect(() => {
const asyncFunction = async () => {
const response = await fetch("https://67f56264913986b16fa4640a.mockapi.io/hikes")
const data = await response.json()
const filteredData = data.filter((data: Hike) => data.favorite == true);
setCards(filteredData)
}
asyncFunction()
}, [])
return (
<div id="favorite-hikes-div">
<h1 id="favorites-header">Favorite Hikes</h1>
<List
setCards={setCards}
cards={cards}
/>
</div>
)
}
Here is my component called List. I pass setCards to list because I use it in delete and update functions.
export default function List({ cards, setCards }: ListProps) {
const deleteCard = async (id: string) => {
try{
const response = await fetch(`${API_URL}/${id}`, {
method: "DELETE",
});
if(!response.ok) {
throw new Error("Network response was not ok.");
}
setCards(cards.filter((card) => id !== card.id)); {/* cards are filtered and new array is created when user clicks delete hike button */}
} catch(error) {
console.error("There was an error when deleting a hike:", error);
throw error;
}
};
const updateCard = async (id: string, updatedCard: Partial<Hike>) => {
try {
const response = await fetch(`${API_URL}/${id}`, {
method: "PUT",
headers: {
'content-type':'application/json'
},
body: JSON.stringify(updatedCard),
});
if (!response.ok) {
throw new Error("Network response was not ok.");
}
const data = await response.json(); {/* Each time a card is updated, the cards are mapped to include the new data */}
setCards( cards.map(card => (
card.id !== id ? card : {
...cards, ...data
}
)) );
} catch (error) {
console.error("There was an error when updating a card:", error);
throw error;
}
};
return (
<div className="list-div">
{cards?.map((card) => (
<HikeCard
setCards={setCards}
deleteCard={deleteCard}
updateCard={updateCard}
key={card.id}
card={card}/>
))}
</div>
);
};
I've tried modifying the code in the useEffect
multiple times, as well as changing the dependency array.
Here is my HikeCard component. Also for clarification, the List component is just a list of cards, and the FavoriteList component filters those cards to only show the "favorites" or cards that have a boolean = true.
export default function HikeCard({ setCards, card, deleteCard, updateCard }: HikeCardProps) {
useEffect(() => {
const asyncFunction = async () => {
const response = await fetch("https://67f56264913986b16fa4640a.mockapi.io/hikes")
const data = await response.json()
setCards(data);
}
asyncFunction()
}, [])
return (
<div id="hike-card">
<div className="heart-icon"
onClick={() => updateCard(card.id, { favorite: !card.favorite })}
>
<div>
</div>
</div>
<div id="hike-card-2" className="card width: 18rem">
<div id="image-div">
<img id="card-image" src={card.imageUrl}
className="card-img-top"
alt={`${card.name} ${location} ${card.miles}`}/>
</div>
<div className="card-body">
<h5 className="card-title">{card.name}</h5>
<h6 id="card-location">{card.location}</h6>
<h6 id="card-miles">{card.miles} miles</h6>
<button onClick={() => deleteCard(card.id)} className="button m-2 btn btn-outline-danger" style={{width: "30%"}}>Delete Hike</button>
<button
onClick={() => updateCard(card.id, { favorite: !card.favorite })}
className="button m-2 btn btn-outline-primary"
style={{width: "30%"}}>Favorite Hike</button>
</div>
</div>
</div>
)
}
[]
instead of[cards]
. It's unknown if the fix is correct because you didn't provide stackoverflow.com/help/mcve , there's no List at leastsetCards(cards => ...
.