一.首先我们要知道useContext和useReducer是什么?
useContext和useReducer都是react中的hook
useContext
1.useContext的定义和作用
它是用于函数组件消费它是一个全局上下文,用于处理跨层级组件通信问题,它避免了组件之间props层层传递的复杂性,它可以直接获取到context中的某个值而不用通过props传递。
2.useContext的使用
创建useContext
js
const ThemeContext = creatContext('light');
使用Provider提供值
jsx
<ThemeContext.Provider value={theme}>
// 这里的Theme为自定义的value值
....// 中间为组件
<ThemeContext.Provider/>
在子组件使用useContext获取值
js
const theme = useContext(ThemeContext)
以下为完整示例代码
jsx
import React, { useContext, useReducer } from 'react';
// 1. 创建 Context
const ThemeContext = React.createContext();
// 2. 创建组件
function App() {
const [theme, toggleTheme] = useReducer(
(state) => (state === 'light' ? 'dark' : 'light'),
'light'
);
return (
// 3. 提供 Context 值
<ThemeContext.Provider value={theme}>
<button onClick={toggleTheme}>切换主题</button>
<Toolbar />
</ThemeContext.Provider>
);
}
// 中间组件(不需要传递 props)
function Toolbar() {
return (
<div>
<ThemedButton />
</div>
);
}
// 4. 使用 useContext 获取 Context 值
function ThemedButton() {
const theme = useContext(ThemeContext);
return (
<button style={{ background: theme === 'dark' ? '#333' : '#eee', color: theme === 'dark' ? '#fff' : '#000' }}>
当前主题:{theme}
</button>
);
}
export default App;
useReducer
1.useReducer的定义和作用
它为管理复杂的状态逻辑提供了一种替代useState的方法,它是一种响应式状态管理。
Reducer是一个纯函数 ,纯函数既是1.相同的输入值会得到相同的输出值2.无副作用不会对外部产生影响如:不改变全局变量,不发送网络请求,不操作DOM等。Reducer它接受两个参数state(当前状态) 和 action(动作)并且返回一个新的状态
dispatch用于发送动作到Reducer中,你调用一个dispatch并传入一个动作对象,reducer会根据整个动作来更新状态
2.useReducer的用法
- 定义 Reducer 函数:根据应用的业务逻辑定义 reducer 函数。该函数接收当前状态和动作作为参数,并返回新的状态。
- 使用 useReducer Hook :在组件中使用
useReducer
来初始化状态和 reducer 函数。useReducer
返回当前状态和 dispatch 方法。 - 分发动作:通过调用 dispatch 方法并传入动作对象来触发状态更新。
jsx
import React, { useReducer } from 'react';
// 定义 Reducer 函数
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
throw new Error();
}
}
function Counter() {
// 初始化状态为 { count: 0 },并指定 reducer 函数
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<>
Count: {state.count}
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
</>
);
}
useContext和useReducer配合使用
什么时候使用useContext 1.当我们想多个层级组件共享状态或配置时 2.避免props一层层传递
什么时候使用useReducer 1.当组件的状态逻辑复杂时,例如涉及多个子值的状态,或者下一个状态依赖于前一个状态。 2.当下一个状态依赖于前一个状态时,使用 useReducer
可以避免一些潜在的副作用问题。
所以我们常常将useContext和useReducer一起使用
1. 创建 Context
首先,创建一个 React Context 来包裹你的应用状态和 dispatch 函数。
jsx
import React, { createContext, useReducer } from 'react';
const AppContext = createContext();
const initialState = {
count: 0,
};
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
throw new Error();
}
}
2. 创建 Provider 组件
接下来,创建一个 Context Provider 组件,该组件内部使用 useReducer
来管理状态,并通过 value
属性向子组件暴露状态和 dispatch 方法。
jsx
export const AppProvider = ({ children }) => {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<AppContext.Provider value={{ state, dispatch }}>
{children}
</AppContext.Provider>
);
};
3. 在顶层组件中使用 Provider
确保在你的应用顶层组件中使用这个 Provider,以便所有子组件都可以访问到状态和 dispatch 方法。
jsx
import React from 'react';
import ReactDOM from 'react-dom';
import { AppProvider } from './AppProvider'; // 假设文件名为 AppProvider.js
import App from './App'; // 你的主应用组件
ReactDOM.render(
<AppProvider>
<App />
</AppProvider>,
document.getElementById('root')
);
4. 使用 useContext 钩子在组件中消费状态
最后,在需要访问状态或触发状态更新的组件中,使用 useContext
钩子来获取当前状态和 dispatch 方法。
javascript
javascript
深色版本
import React, { useContext } from 'react';
import { AppContext } from './AppProvider';
function Counter() {
const { state, dispatch } = useContext(AppContext);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
</>
);
}
export default Counter;
总结
我们通过结合使用 useReducer
和 useContext
,可以构建一个简单而有效的状态管理模式,适用于中小规模的应用。这种方法不仅简化了状态管理,也减少了不必要的代码复杂度。