使用 useContext
+ useReducer
实现的轻量级状态管理,适合中小型 React 应用使用。
createContext
创建两个上下文:StateContext
和 DispatchContext
。useReducer
管理状态逻辑。Provider
组件包裹应用。useGlobalState()
和 useGlobalDispatch()
,分别获取状态和派发方法。store.js
import React, { createContext, useReducer, useContext } from 'react';
// 定义初始状态
const initialState = {
count: 0,
user: null,
};
// 定义 reducer
function reducer(state, action) {
switch (action.type) {
case 'INCREMENT':
return { ...state, count: state.count + 1 };
case 'DECREMENT':
return { ...state, count: state.count - 1 };
case 'SET_USER':
return { ...state, user: action.payload };
default:
throw new Error(`Unknown action type: ${action.type}`);
}
}
// 创建两个上下文
const StateContext = createContext(null);
const DispatchContext = createContext(null);
// 创建 Provider
export function GlobalProvider({ children }) {
const [state, dispatch] = useReducer(reducer, initialState);
return (
{children}
);
}
// 封装 hooks
export function useGlobalState() {
const context = useContext(StateContext);
if (context === undefined) {
throw new Error('useGlobalState must be used within a GlobalProvider');
}
return context;
}
export function useGlobalDispatch() {
const context = useContext(DispatchContext);
if (context === undefined) {
throw new Error('useGlobalDispatch must be used within a GlobalProvider');
}
return context;
}
App.js
import React from 'react';
import { GlobalProvider } from './store';
import Counter from './Counter';
import User from './User';
function App() {
return (
My App
);
}
export default App;
Counter.js
import React from 'react';
import { useGlobalState, useGlobalDispatch } from './store';
function Counter() {
const { count } = useGlobalState();
const dispatch = useGlobalDispatch();
return (
Count: {count}
);
}
export default Counter;
User.js
import React from 'react';
import { useGlobalState, useGlobalDispatch } from './store';
function User() {
const { user } = useGlobalState();
const dispatch = useGlobalDispatch();
const login = () => {
dispatch({ type: 'SET_USER', payload: { name: 'Heo Hao' } });
};
return (
User: {user ? user.name : 'Guest'}
);
}
export default User;