Home > Enterprise >  React - show a component until it is completely ready
React - show a component until it is completely ready

Time:09-26

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.

  • Related