React(五)用useReducer和useContext写简易redux

写在前面:

上上篇博客说到要用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。。这样才算是规范

后续再添加吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值