阅读量:2
文章目录
优雅的加载条
React 应用中使用组件库的加载条(Loading Bar)并保持代码优雅,可以遵循以下步骤。以下示例将使用 Ant Design 组件库的 Spin 组件作为加载条示例,并通过组件化、状态管理和样式组织实现优雅的代码。
安装相应版本的Ant Design
npm install antd
简单场景
1.创建一个 Loading Wrapper 组件
创建一个通用的 Loading Wrapper 组件,用于在任何需要加载状态的地方使用
import React from 'react'; import { Spin } from 'antd'; import PropTypes from 'prop-types'; //加载组件 const LoadingWrapper = ({ loading, children }) => { return ( <Spin spinning={loading}> {children} </Spin> ); }; LoadingWrapper.propTypes = { loading: PropTypes.bool.isRequired, children: PropTypes.node.isRequired, }; export default LoadingWrapper;
2.使用 Loading Wrapper 组件
在需要显示加载状态的组件中使用 LoadingWrapper 组件
import React, { useState, useEffect } from 'react'; import { List, message } from 'antd'; import LoadingWrapper from './LoadingWrapper'; import axios from 'axios'; const DataFetchingComponent = () => { const [loading, setLoading] = useState(true);//初始值要开启加载条 const [data, setData] = useState([]); useEffect(() => { axios.get('/api/data') .then(response => { setData(response.data); setLoading(false);//关闭加载条 }) .catch(error => { message.error('Failed to fetch data'); setLoading(false); }); }, []); return ( <LoadingWrapper loading={loading}> <List dataSource={data} renderItem={item => <List.Item>{item}</List.Item>} /> </LoadingWrapper> ); }; export default DataFetchingComponent;
复杂场景
对于更复杂的应用,可以使用全局状态管理工具(如 Redux 或 Context API)来管理加载状态。
1. 使用 Context API 进行全局加载状态管理
import React, { createContext, useState, useContext } from 'react'; //创建一个 Loading Context: const LoadingContext = createContext(); export const useLoading = () => useContext(LoadingContext); export const LoadingProvider = ({ children }) => { const [loading, setLoading] = useState(false); return ( <LoadingContext.Provider value={{ loading, setLoading }}> {children} </LoadingContext.Provider> ); };
//在顶层组件中使用 LoadingProvider import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; import { LoadingProvider } from './LoadingContext'; ReactDOM.render( <LoadingProvider> <App /> </LoadingProvider>, document.getElementById('root') );
//在组件中使用全局加载状态 import React, { useEffect } from 'react'; import { List, message } from 'antd'; import LoadingWrapper from './LoadingWrapper'; import axios from 'axios'; import { useLoading } from './LoadingContext'; const DataFetchingComponent = () => { const { loading, setLoading } = useLoading(); const [data, setData] = useState([]); useEffect(() => { setLoading(true);//初始值为开启加载 axios.get('/api/data') .then(response => { setData(response.data); setLoading(false); }) .catch(error => { message.error('Failed to fetch data'); setLoading(false); }); }, [setLoading]); return ( <LoadingWrapper loading={loading}> <List dataSource={data} renderItem={item => <List.Item>{item}</List.Item>} /> </LoadingWrapper> ); }; export default DataFetchingComponent;
2.借助Redux进行状态管理
安装 Redux 和相关库:
npm install redux react-redux @reduxjs/toolkit
创建 Redux Store
import { configureStore, createSlice } from '@reduxjs/toolkit'; const loadingSlice = createSlice({ name: 'loading', initialState: false, reducers: { setLoading: (state, action) => action.payload, }, }); export const { setLoading } = loadingSlice.actions; const store = configureStore({ reducer: { loading: loadingSlice.reducer, }, }); export default store;
在顶层组件中提供 Redux Store
import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import App from './App'; import store from './store'; ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') );
在组件中使用 Redux 状态
import React, { useEffect } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { List, message } from 'antd'; import LoadingWrapper from './LoadingWrapper'; import axios from 'axios'; import { setLoading } from './store'; const DataFetchingComponent = () => { const loading = useSelector((state) => state.loading); const dispatch = useDispatch(); const [data, setData] = useState([]); useEffect(() => { dispatch(setLoading(true)); axios.get('/api/data') .then(response => { setData(response.data); dispatch(setLoading(false)); }) .catch(error => { message.error('Failed to fetch data'); dispatch(setLoading(false)); }); }, [dispatch]); return ( <LoadingWrapper loading={loading}> <List dataSource={data} renderItem={item => <List.Item>{item}</List.Item>} /> </LoadingWrapper> ); }; export default DataFetchingComponent;
知识加油站
Redux和Context API 的关系
Redux 和 Context API 都是用于状态管理的工具,但它们有不同的特点和使用场景。以下是它们的主要区别和关系:
Redux
Redux 是一个流行的状态管理库,提供了一个集中式的状态存储和不可变状态更新的机制。Redux 适用于大型应用程序,具有以下特点:
- 集中式状态管理:所有的状态存储在一个单独的 store 中,便于调试和管理。
- 不可变状态更新:通过 actions 和 reducers 更新状态,确保状态不可变。
- 中间件支持:支持异步 actions 和其他中间件(如 redux-thunk、redux-saga)来处理复杂的逻辑。
- 丰富的生态系统:有许多工具和库可以与 Redux 集成,如 Redux DevTools。
Context API
Context API 是 React 提供的内置状态管理解决方案,适用于较小或中等规模的应用程序。它的特点包括:
- 简洁易用:内置于 React 中,无需额外安装。
- 组件树上下文传递:允许在组件树中传递数据,避免了 prop drilling。
- 轻量级:适合简单的状态管理场景,特别是当状态变化不频繁时。
Redux 和 Context API 的关系
- 使用场景:Redux 适用于复杂和大型应用程序,需要集中式状态管理和复杂的状态更新逻辑;Context API 则适用于较小和中等规模的应用程序,或需要简单状态传递的场景。
- 复杂性:Redux 提供了更多的结构和工具来管理复杂的状态和逻辑,但也引入了更多的复杂性;Context API 更加简洁,适合轻量级的状态管理。
- 性能:Context API 可能在频繁状态变化时导致性能问题,因为每次状态变化都会重新渲染使用该上下文的组件树;Redux 则通过连接(connect)和选择器(selectors)优化了这种问题。