Creating a React component with a circular loader that displays percentage and texts using Material-UI

I've developed a CircularLoader component using Material UI. The issue I'm facing is that when the variant is set to 'indeterminate', the loader should display without any percentage indication. However, if the variant is 'determinate', then the loader should show the percentage inside it along with the regular text content.

For the complete code demo, check out this SITE

const CircularLoader = (props) => {
  const {
    height = "auto",
    color = "primary",
    text = "",
    value = 0,
    variant = "indeterminate"
  } = props;

  return (
    <Grid
      component="div"
      container
      justifyContent="center"
      alignItems="center"
      flexDirection="column"
      sx={{ height }}
    >
      <CircularProgress
        // variant={variant}
        // value={value}
        disableShrink
        color={color}
        thickness={4}
        sx={{ marginBottom: "0.5rem" }}
      />
      <Typography variant="body1" component="div" color={color}>
        {text}
      </Typography>
    </Grid>
  );
};
export default CircularLoader;

Answer №1

If you prefer to separate these components, it might be the best approach since they possess distinct props. However, if you wish to combine them into a single component, you must assign a dynamic value ranging from 0 to 100 to the determinate variant. To understand this better, refer to the code example in the documentation source code example.

In your scenario, you might want to use a ternary operator to decide which variant to render. As a simple demonstration, the following snippet should suffice (please note that I'm neglecting the value prop and imitating it with progress for illustrative purposes):

import React from "react";
import Grid from "@mui/material/Grid";
import Stack from "@mui/material/Stack";
import Typography from "@mui/material/Typography";
import CircularProgress from "@mui/material/CircularProgress";
import Box from '@mui/material/Box';

const CircularLoader = ({
  height = "auto",
  color = "primary",
  text = "",
  value = 0,
  variant = "indeterminate"
}) => {
  const [progress, setProgress] = React.useState(0);

  React.useEffect(() => {
    const timer = setInterval(() => {
      setProgress((prevProgress) =>
        prevProgress >= 100 ? 0 : prevProgress + 10
      );
    }, 800);

    return () => {
      clearInterval(timer);
    };
  }, []);

  return (
    <Grid
      component="div"
      container
      justifyContent="center"
      alignItems="center"
      flexDirection="column"
      sx={{ height }}
    >
      {variant === "indeterminate" ? (
        <CircularProgress />
      ) : (
      <Stack spacing={2} direction="row">
       <Box sx={{ position: 'relative', display: 'inline-flex' }}>
        <CircularProgress variant="determinate" value={progress}/>
        <Box
        sx={{
          top: 0,
          left: 0,
          bottom: 0,
          right: 0,
          position: 'absolute',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
        }}
      >
        <Typography variant="caption" component="div" color="text.secondary">
          {`${Math.round(progress)}%`}
        </Typography>
      </Box>
    </Box>
        </Stack>
      )}

      <Typography variant="body1" component="div" color={color}>
        {text}
      </Typography>
    </Grid>
  );
};
export default CircularLoader;

progress is only being simulated here for demonstration purposes. In actuality, you should pass down the progress as value through props and utilize it in the CircularProgress component (it should reflect some dynamic value associated with the real loading progress state).

Link to Sandbox

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Click on the sort icon in React JS to change its state

I need to update the sort icon in my table header when a user sorts a column. Here is the current implementation of my sorting function: var headerColumns = []; var IconType = 'triangle'; var IconSort = 'top'; var onToggleO ...

In ReactJS, removing the value from Material-UI TextField displays the previously entered text

I have implemented a SearchBar feature in my ReactJS application. Below is the code snippet for the SearchBar: import React, { useState, useImperativeHandle, forwardRef, useEffect } from 'react'; import { makeStyles } from '@material-ui/core ...

Gradually appear/disappear div element with a delay added

Storing divs in an array and deleting them after appending is my current method. Now, I'm looking to incorporate a fade-in and fade-out effect on each div with a delay. Check out this code snippet : var arr = $(".notification"); function display ...

The chosenValues.filter method hit an unexpected token; a comma was anticipated

I have encountered a syntax error in the following line: queryComponents: prevState.seletedValues.filter((a, i) => (i !== index)); I am attempting to swap out splice with filter. I've attempted modifying brackets, both adding and removing them, b ...

After the automation is finished, I am interested in outputting the IMDB rating of a movie or series to the terminal

I prefer using Google search to find the element because I find it easier to navigate compared to IMDB. import selenium.webdriver as webdriver print("This script is designed to retrieve the IMDb rating of a movie or TV series!!!") def get_results(search_ ...

Customizable user profile page

I'm currently working with twitter bootstrap. My goal is to design a profile page featuring an edit button positioned on the top left corner. Upon clicking this button, all the profile details will transition into editable form fields (which I bel ...

How to Set Focus on React Element Dynamically Without Using an Arrow Function

I have recently been working on a code snippet that is performing very efficiently: import React, { RefObject, useReducer, useRef, useState } from 'react'; import TextField from '@material-ui/core/TextField'; const MyComponent ...

I am facing an issue with my React Native splash screen

I am facing issues with the React Native splash screen implementation. I followed all the instructions on the GitHub repository, but the problem persists. The problem arises after setting up React Native Splash Screen in my app. Despite following all the ...

Retrieving user information from Firestore and storing it in the state within a React component

I am having trouble saving user data into state even though I have created a function to retrieve data from Firestore and call it in the handleSubmit function of my login component. function fetchUserData() { return db .collection("customers&q ...

Trouble arises with Pagination feature of Mui Data Table

Currently, I am working on a project that involves retrieving data from the CoinMarketCap API and presenting it in an MUI Data Table (specifically a StickyHeader Data Table). However, I have been encountering difficulties with changing the color of the tex ...

styled-components: the parent's styles take precedence over the child's styles

image export const LogOutButton = styled.button` display: inline-block; .... `; export default styled(ThemedApp)` .... button { .... display: flex; .... } `; Upon inspection, it is evident that the Logout button (with class gBuhXv) ...

ngInfiniteScroll Activates on Every Scroll Occurrence

Implementing ngInfiniteScroll for endless scrolling on my website has required me to set the height of the outer div to a specific value. Without this adjustment, the Infinite Scroll feature activates unintentionally. <div style="height: 1px"> &l ...

PropTypes for functions that are being passed down in the component tree

Could you please provide guidance on how to properly set up proptypes for the fields name, label, and onChange in the code snippet below? I have tried setting up proptypes but they don't seem to be functioning correctly. function FilterCheckbox(prop ...

Nextjs application routers offer dynamic routing functionality and the ability to generate metadata

Struggling with static site generation while building a blog site in nextjs with app router? If you've read through Next.js official documentation and still need assistance, check out my project structure pictured https://i.stack.imgur.com/ZOYkf.png. ...

No matter how much I try, the text refuses to align with the top-left corner

I have been working on creating a loading screen, but I am facing an issue with aligning the h1 tag selected to the top left. As a young developer at the age of 13, I am quite confused. I attempted to use the following CSS properties: vertical-align: top; ...

When using a Redux action type with an optional payload property, TypeScript may raise complaints within the reducer

In my react-ts project, I define the following redux action type: type DataItem = { id: string country: string population: number } type DataAction = { type: string, payload?: DataItem } I included an optional payload property because there are tim ...

Text Box: Add a touch of flair with resizing

One interesting feature on my webpage is a textarea that can be resized using resize:both; I am looking for a way to apply a specific style to this textarea only when the user resizes it. While I would prefer to achieve this with CSS alone, it seems like ...

Styling for Print Media: Adjusting the horizontal spacing between inline elements

I have been developing a custom AngularJS point-of-sale (POS) system that requires printing receipts upon completing a sale. To achieve this, I am using ng-print to print out a sales summary displayed within a specific div element after hiding all other un ...

New Approach to Icon Menu/ PopOver Menu Design with Material UI

Currently, I am working on a project that involves material-ui and I have encountered an issue with using menus. I need to be able to select multiple values from the menu, but DropDown does not support this functionality. Similarly, other menus do not of ...

When positioning 2 divs on top of each other, rotating one by 180 degrees causes it to be considered secondary in the visibility hierarchy. What is the reason behind this?

While delving into the realm of HTML, I stumbled upon a concept that has left me perplexed. Upon stacking two divs on top of each other, I observed an interesting phenomenon where rotating the second div by 180deg (i.e transform:rotateY(180deg)), causes t ...