写在前面:
上上篇博客说到要用useReducer和useContext写一个简易功能的redux, 所以现在来啦
(一)用useReducer实现基本功能
redux和useReducer的使用步骤都差不多,创建reducer函数,再通过dispatch函数传入action,实现对state的修改
所以直接写一个useReducer的例子,还是之前那个计数器加减法:
// views/counter/index,jsx
import { useReducer } from "react"
function reducer(state, action){
switch(action.type){
case 'increment':{
return {
num:state.num + action.playload
}
}
case 'decrement':{
return {
num:state.num - action.playload
}
}
default:{
return state
}
}
}
const initialState = {num:0}
function Counter() {
const [state,dispatch] = useReducer(reducer,initialState)
return (
<>
<div>counter组件</div>
<div>{state.num}</div>
<button onClick={() => { dispatch({type:'increment',playload:5}) }}>+5</button>
<button onClick={() => { dispatch({ type: 'decrement', playload: 5 }) }}>-5</button>
</>
)
}
export default Counter
(二)拆分reducer并加入useContext
将useReducer部分都提取到store文件夹里
// store/reducer.js
// 存放reducer
export const initialState = {num:0}
export function reducer(state, action) {
switch (action.type) {
case 'increment': {
return {
num: state.num + action.playload
}
}
case 'decrement': {
return {
num: state.num - action.playload
}
}
default: {
return state
}
}
}
使用useContext创建ContextProvider组件
// store/context.js
// 创建context
import { useReducer, createContext } from "react";
import {initialState, reducer} from "./reducer";
// 导出createContext 需要使用store的子组件需要通过useContext获取
export const Store = createContext(null)
function ContextProvider({ children }){
const [state,dispatch] = useReducer(reducer,initialState)
return (
<>
<Store.Provider value={{ state, dispatch }}>
{children}
</Store.Provider>
</>
)
}
// 导出provider组件
export default ContextProvider
(三)将store放在全局
使用useContext Hook的provider组件 提升store的作用域,让全局的子组件都能访问到
import Counter from "./views/Counter"
import ContextProvider from "./store/context"
function App() {
return (
<>
{/* 提升作用域 */}
<ContextProvider>
<Counter></Counter>
</ContextProvider>
</>
)
}
export default App
在counter子组件使用store
import { useContext } from "react"
import { Store } from "../../store/context"
function Counter() {
const store = useContext(Store)
return (
<>
<div>counter组件</div>
<div>{store.state.num}</div>
<button onClick={() => { store.dispatch({type:'increment',playload:5}) }}>+5</button>
<button onClick={() => { store.dispatch({ type: 'decrement', playload: 5 }) }}>-5</button>
</>
)
}
export default Counter
大功告成!!!还是响应式的,简直爽歪歪
(四)总结
这里只是简单的写了个redux那种全局状态库的感觉,但是稍微复杂一点还需要涉及到多个子仓库的整合那样,梭哈,也还需要细分出action.js和constant.js。。这样才算是规范
后续再添加吧!