Using the React Context API to Create a Loader Component
Tags: webdev, beginners, react, typescript
Published: 2024-04-01 05:32:25

Web applications frequently include loading indicators, which give users indicators of progress while information or data is being retrieved or processed. In this article, we'll use React's Context API to develop a reusable loader component.

## Setting Up the Project

First, let's set up a new React project. Make sure you have Node.js and npm installed, and then run the following commands:

```
npm init @vitejs/app loader-provider-demo --template react
cd loader-provider-demo
```

## Creating the Loader Context

Create a new file named `LoaderContext.tsx` in the `src` folder. This file will define our loader context and provide the necessary context provider and consumer components.

```
import React, { ReactNode, createContext, useState } from 'react';
import { Loader } from '../component/Loader';

type LoaderContext = {
  showLoader: (message: string) => void;
  hideLoader: () => void;
};

type LoaderContextProvider = {
  children: ReactNode;
};

export const LoaderContext = createContext<LoaderContext | undefined>(
  undefined
);

export const LoaderProvider: React.FC<LoaderContextProvider> = ({
  children,
}) => {
  const [isVisible, setIsVisible] = useState<boolean>(false);
  const [loaderMessage, setLoaderMessage] = useState<string | undefined>();

  const contextValue: LoaderContext = {
    showLoader: (message) => {
      setLoaderMessage(message);
      setIsVisible(true);
    },
    hideLoader: () => {
      setIsVisible(false);
    },
  };

  return (
    <LoaderContext.Provider value={contextValue}>
      {isVisible && <Loader message={loaderMessage} />}
      {children}
    </LoaderContext.Provider>
  );
};

```
Create a new file named `useLoader.ts` in the `src/hooks` folder.

```
import { useContext } from "react";
import { LoaderContext } from "../context/LoaderProvider";

export const useLoader = ()=>{
  const context = useContext(LoaderContext);
    if (!context) {
      throw new Error("useLoader must be used within a LoaderProvider");
    }
    return context;
}
```

## Creating the Loader Component
Next, let's create the Loader component ( create `Loader.tsx` file in `src/components/loader` folder) that will display the loading indicator:

```
import React from 'react';
import "./Loader.css";

type Loader = {
  message: string | undefined;
};

export const Loader: React.FC<Loader> = ({ message }) => {
  return (
    <div className="loader">
      <span className="spinner"></span>
      <span className="loader-message">{message}</span>
    </div>
  );
};

```

## Styling the Loader Component

Add the following CSS code to a file named `Loader.css` in your `src/components/loader` folder to style the loader component:

```
.loader{
  position: absolute;
  z-index: 99999;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 100vw;
  height: 100vh;
  background-color: white;
  opacity: 0.9;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
.spinner{
  width: 60px;
  height: 60px;
  border: 10px solid #ccc;
  border-top: 10px solid #2F73A3;
  border-radius: 50%;
  animation: spin 1.5s linear infinite;
}
@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
.loader-message{
  margin-top: 10px;
  font-size: 22px;
  font-weight: 600;
  color : #2F73A3;
  font-family: Verdana, Geneva, Tahoma, sans-serif;
}

```

## Using the Loader Context
Now, let’s use our `LoaderProvider` in the `main.tsx` file:

```
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App.tsx';
import './index.css';
import { LoaderProvider } from './context/LoaderProvider.tsx';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <LoaderProvider>
      <App />
    </LoaderProvider>
  </React.StrictMode>
);

```
## Using the Custom Hook to Show Loader
In any component where you want to show the loader, you can use the `useLoader` custom hook:

```
import './App.css';
import { useLoader } from './hooks/useLoader';

function App() {
  const { showLoader, hideLoader } = useLoader();

  return (
    <>
      <button onClick={() => showLoader("Please wait!")}>Show Loader</button>
      <button style={{position:'absolute',zIndex:"99999"}} onClick={() => hideLoader()}>hide Loader</button>
    </>
  );
}

export default App;

```
## Conclusion
In this tutorial, we've created a loader component using React's Context API, allowing us to manage loading states globally across our application. This approach provides a clean and efficient way to handle loading indicators and can be easily extended to suit different use cases.

Feel free to customize the loader component's appearance and behavior to fit your application's needs. 

Happy coding!