[React] Loading indicator with React Context API & Hooks

by Hieu Nguyen
2.6K views

Loading indicator có lẽ là component huyền thoại mà dự án nào cũng cần đến. Hôm nay mình sẽ hướng dẫn các bạn viết nó thành dạng global component để có thẻ được gọi tại bất kỳ đâu trong ứng dụng của bạn. Chúng ta cùng bắt đầu nhé.

Để hiểu thêm về React Context API & Hooks các bạn tham khảo thêm tại đây:

Chúng ta bắt đầu bằng việc tạo một dự án mới sử dụng React nhé. Trong bài viết này mình sẽ sử dụng create-react-app cùng với yarn để tạo project mới. Các bạn xem hướng dẫn cài yarn tại đây nhé.

Tạo một project mới

  • Cài create-react-app package:
hieunv@HieuNV ~ % yarn global add create-react-app
yarn global v1.22.0
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 🔨  Building fresh packages...
success Installed "[email protected]" with binaries:
      - create-react-app
✨  Done in 14.08s.
  • Sau khi cài xong thì các bạn tạo project mới như sau:
yarn create react-app loading
Cấu trúc project được tạo bằng create-react-app

Tạo React context mới để lưu trạng thái của Loading component

context/loading.js

import React, { useContext } from 'react';

export const LoadingContext = React.createContext();

export const useLoading = () => useContext(LoadingContext);

Tạo LoadingProvider để lưu trạng thái loading như là một global state.

providers/LoadingProvider.jsx

import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { LoadingContext } from '../../contexts/loading';

export function LoadingProvider(props) {
  const [loading, setLoading] = useState(false);

  return (
    <LoadingContext.Provider
      value={{
        loading: loading,
        show: () => setLoading(true),
        hide: () => setLoading(false)
      }}>
      {props.children}
    </LoadingContext.Provider>
  );
}

LoadingProvider.propTypes = {
  children: PropTypes.node
};

Như các bạn nhìn thấy trong đoạn mã trên chúng ta đã sử dụng LoadingContext truyền trang thái loading và các hàm showhide xuống các component con thông qua React Context.

Tại App component bạn đặt LoadingProvider là component cao nhất để tất các các component con bên trong có thể gọi các hàm showhide khi cần thiết.

App.js

import React from 'react';
import { LoadingProvider } from './providers/LoadingProvider';
import { useLoading } from './context/loading.js';
import logo from './logo.svg';

import './App.css';

function App() {
  const { show, hide } = useLoading();
  return (
    <LoadingProvider>
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <p>
            Edit <code>src/App.js</code> and save to reload.
          </p>
          <a className="App-link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer">
            Learn React
          </a>
        </header>
      </div>
    </LoadingProvider>
  );
}

export default App;

Tại component bạn muốn gọi show hay hide loading thì chỉ cần thực hiện như sau:

  • import hàm useLoading() được khai báo trong context/loading.js
import { useLoading } from './context/loading.js';
  • Trong component bạn sử dụng hook useLoading để lấy các hàm showhide:
const { show, hide } = useLoading();

Giờ chúng ta sửa lại một chút ở LoadingProvider để có thể show loading indicator

import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { LoadingContext } from '../../contexts/loading';

function Loading() {
  return <div>Loading...</div>;
}

export function LoadingProvider(props) {
  const [loading, setLoading] = useState(false);

  return (
    <LoadingContext.Provider
      value={{
        loading: loading,
        show: () => setLoading(true),
        hide: () => setLoading(false)
      }}>
      <>
        {loading && <Loading />}
        {props.children}
      </>
    </LoadingContext.Provider>
  );
}

LoadingProvider.propTypes = {
  children: PropTypes.node
};

Các bạn để ý component Loading nhé. Chúng ta chỉ cần thêm một chút kỹ thuật css để cho component này đề lên trên tất cả các component khác bằng z-index đã có được loading indicator có thể được gọi ở bất kỳ đâu rồi.

Cám ơn các bạn đã theo dõi bài viết. Hy vọng bài viết có thể giúp ích cho dự án của các bạn.

Leave a Comment

* By using this form you agree with the storage and handling of your data by this website.

You may also like