I'm new using React and I´m having a trouble trying to render/show a component until it is completely ready.
I have a slider where I can click and choose different categories from. It works, and shows the corresponding projects to the category clicked/selected, but when I click each different category it immediately shows the projects/components with no information on it, it is just an empty component and after a seconds barely immediately it shows the component with its corresponding data
-I would like to show a loading animation before the projects are ready and completely loaded with their data, or don't show anything until the components/projects are ready.
Data used to render projects:
export default [
{
title: "Java",
projects: [
{
imagePath: "/images/my_projects/i1.jpg",
imageName: "img1",
name: "Vision VR",
relatedCategories: [{ category: "Java" }, { category: "React" }],
desc: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus commodo fringilla enim vitae rhoncus. Donec pulvinar viverra vehicula.",
previewLink: "#",
githubLink: "https://github.com",
},
],
},
{
title: "Python",
projects: [
{
imagePath: "/images/my_projects/i2.jpg",
imageName: "img2",
name: "Jiray uo",
relatedCategories: [{ category: "Reo" }, { category: "Nau" }],
desc: "In urna ipsum, dignissim volutpat porta sit amet, dignissim in magna. Donec a turpis accumsan, varius eros eget, venenatis nulla.",
previewLink: "#",
githubLink: "https://github.com",
},
{
imagePath: "/images/my_projects/i2b.jpg",
imageName: "img2-b",
name: "Futon se",
relatedCategories: [{ category: "Mosca" }, { category: "Nau" }],
desc: "Vivamus mattis consequat tristique. Etiam condimentum sapien augue, vitae dapibus enim rhoncus vel. Nunc a lacinia ante.",
previewLink: "#",
githubLink: "https://github.com",
},
],
},
{
title: "Spring",
projects: [
{
imagePath: "/images/my_projects/i3.jpg",
imageName: "img3",
name: "Saku er",
relatedCategories: [{ category: "Der" }, { category: "Nau" }],
desc: "Phasellus suscipit, odio sit amet pharetra porttitor, nunc massa vulputate dolor, in euismod neque neque eget ante.",
previewLink: "#",
githubLink: "https://github.com",
},
],
},
];
Main component, a short version of my code:
import MyProjectsEachProject from "./MyProjectsEachProject/MyProjectsEachProject";
import categories from "./MyProjectsEachCategory/MyProjectsCategoriesData";
const MyProjects = () => {
// setCategorySelected is triggered in another component, so it works fine
const [categorySelected, setCategorySelected] = useState(categories[0].title);
return (
<div className="my-projects-container">
<div className="projects-to-show-container">
{categories.map((eachCategory) =>
// if the projects belong to the category we want to display
eachCategory.title === categorySelected
? eachCategory.projects.map((eachProject) => {
return (
<MyProjectsEachProject
key={eachProject.name}
imagePath={eachProject.imagePath}
imageName={eachProject.imageName}
name={eachProject.name}
relatedCategories={eachProject.relatedCategories}
desc={eachProject.desc}
previewLink={eachProject.previewLink}
githubLink={eachProject.githubLink}
/>
);
})
: null
)}
</div>
</div>
);
};
export default MyProjects;
component of each project:
import React from "react";
import "./myProjectsEachProject.css";
function MyProjectsEachProject({
imagePath,
imageName,
name,
desc,
previewLink,
githubLink,
}) {
return (
<div className="each-project-container">
<div className="each-project-img-container">
<img src={imagePath} alt={imageName} />
</div>
<p className="each-project--title">{name}</p>
<p className="each-project--desc">{desc}</p>
<div className="each-project--btns-container">
<a href={previewLink}>
Preview
</a>
<a href={githubLink}>
GitHub repo
</a>
</div>
</div>
);
}
export default MyProjectsEachProject;
Another question I have is: is it correct to use an array to store the data of the projects or should I use a json file instead? because I 'seen that many people use a fetch function with an api url or a local .json file
CodePudding user response:
It is possible to listen to the property and return null or spinner until it is ready. Let's say if categories are empty or an empty array return a login indicator
For example,
import MyProjectsEachProject from "./MyProjectsEachProject/MyProjectsEachProject";
import categories from "./MyProjectsEachCategory/MyProjectsCategoriesData";
const MyProjects = () => {
// setCategorySelected is triggered in another component, so it works fine
const [categorySelected, setCategorySelected] = useState(categories[0].title);
if (!categories || categories.length === 0) { // this can give you the idea
return <div>Loading...</div>
}
return (
<div className="my-projects-container">
<div className="projects-to-show-container">
{categories.map((eachCategory) =>
// if the projects belong to the category we want to display
eachCategory.title === categorySelected
? eachCategory.projects.map((eachProject) => {
return (
<MyProjectsEachProject
key={eachProject.name}
imagePath={eachProject.imagePath}
imageName={eachProject.imageName}
name={eachProject.name}
relatedCategories={eachProject.relatedCategories}
desc={eachProject.desc}
previewLink={eachProject.previewLink}
githubLink={eachProject.githubLink}
/>
);
})
: null
)}
</div>
</div>
);
};
export default MyProjects;
or
import React from "react";
import "./myProjectsEachProject.css";
function MyProjectsEachProject({
imagePath,
imageName,
name,
desc,
previewLink,
githubLink,
}) {
if (!name) {
return <div>Loading...</div> // you can return a spinner component instead or just a div like this.
}
return (
<div className="each-project-container">
<div className="each-project-img-container">
<img src={imagePath} alt={imageName} />
</div>
<p className="each-project--title">{name}</p>
<p className="each-project--desc">{desc}</p>
<div className="each-project--btns-container">
<a href={previewLink}>
Preview
</a>
<a href={githubLink}>
GitHub repo
</a>
</div>
</div>
);
}
export default MyProjectsEachProject;
Also, I would suggest using JSON. It is more common.