I am trying to render and then re-render using array.map() an array of objects. The useEffect is called whenever the state(selected) changes for the options ('All','BACKEND','FRONTEND','ML').
The
MY ISSUE:
The rendering of the data is fine but I have added a basic animation which fades the elements in one by one using "react-awesome-reveal" library. I did the same with plain CSS so I don't think my error lies here.
The animation works if you refresh or direct towards the page or THE NUMBER OF ELEMENTS TO BE RE-RENDERED IS MORE THAN THE ELELEMNTS ON SCREEN THE LATER ELEMENTS WILL HAVE THE ANIMATION.
EG: If I go from "Frontend" to "Backend" then there are currently 2 elements in the DOM but now 3 need to be re-rendered so the first 2 elements do not carry the animation but the third does. It also works in the reverse where if I go from "All" 9 elements to "ML" 2 elements the elements are automatically rendered without the animation.
It seems like the DOM is looking at what is already rendered and deciding to not re-render the elements that are already there thus the FADE animation is not working.
Ideally I want the setData(...) to create a new state so that the array is mapped as if it the page was refreshed.
Here is the code snippet:
import {
backendCourses,
frontendCourses,
mlCourses,
allCourses,
} from "../../data";
export default function Courses() {
const [selected, setSelected] = useState();
const [data, setData] = useState(allCourses);
const list = [
{ id: "all", title: "All" },
{ ....},
...
];
useEffect(() => {
switch (selected) {
case "all":
setData(Array.from(allCourses));
break;
case "backend":
setData([...backendCourses]);
case ....
}, [selected]);
return (
<div className="courses" id="courses">
<h1>Courses</h1>
<ul>
{list.map((item, index) => (
<CoursesList
...
active={selected === item.id}
setSelected={setSelected}
/>
))}
</ul>
<div className="container">
{data.map((item, index) => (
<Fade ...>
<div ...>
<img ...>
</div>
</Fade>
))}
</div>
</div>
);
}
//CoursesList Component
export default function CoursesList({ id, title, active, setSelected }) {
return (
<li
className={active ? "coursesList active" : "coursesList"}
onClick={() => setSelected(id)}
>
{title}
</li>
);
}
The mapping of the elements using Fade from "react-awesome-reveal" FULL-CODE.
<div className="container">
{data.map((item, index) => (
<Fade delay={index * 500}>
<div className="item">
<img src={item.img} alt={item.title} id={index}></img>
<a href={item.url} target="_blank">
<h3>{item.title}</h3>
</a>
</div>
</Fade>
))}
Here is the full useEffect hook code. I initially thought I was not creating a new array only referencing it but have tried multiple ways to clone the array without success. The courses data for now is hard-coded and just read from a file.
useEffect(() => {
switch (selected) {
case "all":
setData(Array.from(allCourses));
break;
case "backend":
setData([...backendCourses]);
break;
case "frontend":
setData([...frontendCourses]);
break;
case "ml":
setData([...mlCourses]);
break;
default:
setData([...allCourses]);
}
}, [selected]);
Sorry for the long post but trying to be as detailed as I can.


