Create loader component in react

Learn how to create loader component in react.

A loader is use to represent that some processing is going on and the current page, tab, section or element is unavailable at the moment.

React loader component

We are going to create the above component which will be extendable. It will have the following characteristics.

  • Loader can be a image or CSS animation.
  • It can full screen or default size that has been provided.
  • We can update the properties of the CSS loader.

Now as you may have got good idea about what we are going to build. Let us start the development.

We will require few extra packages for our help.

  • prop-types: To validate the props that will be recieved.
  • classnames: This helps to use CSS classes as javascript objects, we just need to name our CSS file as filename.module.css.

First, import all the packages at the top and define the component.

import React from "react";
import PropTypes from "prop-types";
import cx from "classnames";
import styles from "./index.module.css";

const Loader = props => {
  //Other code will go here
}

export default Loader;

We have created a functional component because we does not have to maintain any state.

I prefer to validate all props while creating the component so that I have a good idea about what all things are required.

Also set the default props if the expected props are missing.

Loader.propTypes = {
  image: PropTypes.element,
  fullScreen: PropTypes.bool.isRequired,
  bgColor: PropTypes.string.isRequired,
  width: PropTypes.string.isRequired,
  height: PropTypes.string.isRequired,
  loaderColor: PropTypes.shape({
    top: PropTypes.string,
    bottom: PropTypes.string,
    left: PropTypes.string,
    right: PropTypes.string
  }).isRequired
};

Loader.defaultProps = {
  image: null,
  fullScreen: false,
  bgColor: "rgba(0, 0, 0, 0)",
  loaderColor: {
    top: "blue",
    bottom: "pink",
    left: "green",
    right: "red"
  },
  width: "140px",
  height: "140px"
};

These are some of the props which need according to the type component we are going to build.

image will be an element and if it is missing then default CSS loader will shown. width & height is for the CSS loader as well the loaderColor.

As you can see in the images CSS loader has border on which these colors will be used.

bgColor will be used in the background for the fullscreen.

Lets now create the layout.

const { image, fullScreen, bgColor, loaderColor, width, height } = props;
  const { top, bottom, left, right } = loaderColor;

  const loaderStyle = {
    borderTopColor: top,
    borderBottomColor: bottom,
    borderLeftColor: left,
    borderRightColor: right,
    width,
    height
  };

  return (
    <div
      className={cx(styles.loaderArea, {
        [styles.fullscreen]: fullScreen
      })}
      style={{ backgroundColor: bgColor }}
    >
      {image ? (
        image
      ) : (
        <div className={styles.loader} style={loaderStyle}></div>
      )}
    </div>
  );

One of the most major advantage of using classnames is that we can dynamically add the CSS classes.

className={cx(styles.loaderArea, {
  [styles.fullscreen]: fullScreen
 })}

Will add the styles.fullscreen when fullScreen is true.

Other things are straight forward, we are just assigning proper style to each elements.


Complete code of react loader component

import React from "react";
import PropTypes from "prop-types";
import cx from "classnames";
import styles from "./index.module.css";

const Loader = props => {
  const { image, fullScreen, bgColor, loaderColor, width, height } = props;
  const { top, bottom, left, right } = loaderColor;

  const loaderStyle = {
    borderTopColor: top,
    borderBottomColor: bottom,
    borderLeftColor: left,
    borderRightColor: right,
    width,
    height
  };

  return (
    <div
      className={cx(styles.loaderArea, {
        [styles.fullscreen]: fullScreen
      })}
      style={{ backgroundColor: bgColor }}
    >
      {image ? (
        image
      ) : (
        <div className={styles.loader} style={loaderStyle}></div>
      )}
    </div>
  );
};

Loader.propTypes = {
  image: PropTypes.element,
  fullScreen: PropTypes.bool.isRequired,
  bgColor: PropTypes.string.isRequired,
  width: PropTypes.string.isRequired,
  height: PropTypes.string.isRequired,
  loaderColor: PropTypes.shape({
    top: PropTypes.string,
    bottom: PropTypes.string,
    left: PropTypes.string,
    right: PropTypes.string
  }).isRequired
};

Loader.defaultProps = {
  image: null,
  fullScreen: false,
  bgColor: "rgba(0, 0, 0, 0)",
  loaderColor: {
    top: "blue",
    bottom: "pink",
    left: "green",
    right: "red"
  },
  width: "140px",
  height: "140px"
};

export default Loader;

Complete style code of react loader

Native CSS loader is created using animations.

//index.module.css
.loaderArea {
  display: inline-block;
}

.fullscreen {
  position: fixed;
  width: 100vw;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 999;
}

.loader {
  border: 16px solid #f3f3f3;
  border-top: 16px solid #3498db;
  border-radius: 50%;
  animation: spin 1.5s linear infinite;
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

Input

import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import Loader from "./Components/Loader";
import * as serviceWorker from "./serviceWorker";
import image from "./loader.gif";

ReactDOM.render(
  <div className="abc">
    {/* With image */}
    <Loader
      image={
        <img
          src={image}
          alt="loader"
          style={{ display: "inline-block", verticalAlign: "middle" }}
        />
      }
      fullScreen={true}
    />

    {/* default */}
    <Loader
      fullScreen={true}
      width="120px"
      height="120px"
      bgColor="rgba(0,0,0,.5)"
    />
  </div>,
  document.getElementById("root")
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();