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
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 show
và hide
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 show
và hide
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 trongcontext/loading.js
import { useLoading } from './context/loading.js';
- Trong component bạn sử dụng hook
useLoading
để lấy các hàmshow
vàhide
:
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.