useReducer用法

简介

useReducer是React提供的一个高级Hook,它不像useEffect、useState、useRef等必须hook一样,没有它我们也可以正常完成需求的开发。

简单来说 reducer是一个函数(state, action) => newState:接收当前应用的state和触发的动作action,计算并返回最新的state

例子

常规
import {useCallback, useState} from "react";

export const useUndo = <T>(initialPresent:T) =>{


    const [state,setState] = useState<{
        past:T[],
        present:T,
        future:T[]
    }>({
        past:[],
        present:initialPresent,
        future:[]

    })

    const canUndo = state.past.length !== 0;
    const canRedo = state.future.length !== 0;

    const undo = useCallback(() =>{
        setState(currentState => {
            const {past,present,future} = currentState;
            if (past.length === 0) return currentState;

            const previous = past[past.length - 1];

            const newPast = past.slice(0,past.length - 1);
            return {
                past:newPast,
                present:previous,
                future:[present,...future]
            }

        })

        },[])

    const redo = useCallback(() => {
        setState(currentState => {
            const {past,present,future} = currentState;
            if (future.length === 0) return currentState;

            const next = future[0];
            const newFurture = future.slice(1);

            return {
                past:[...past,present],
                present:next,
                future:newFurture
            }


        })
    },[])

    const  set = useCallback((newPresent: T) =>{
        setState(currentState => {
            const {past,present} = currentState;
            if (newPresent === present) return currentState;
            return{
                past:[...past,present],
                present:newPresent,
                future:[]
            }

        })

    },[])

    const reset = useCallback((newPresent:T) =>{
        setState(currentState => {
            return {
                past:[],
                present:newPresent,
                future:[]
            }
        })

    },[])

    return [
       state,
        {set,reset,undo,redo,canUndo,canRedo}
    ] as const
}

使用useReducer
import {useCallback, useReducer, useState} from "react";

const UNDO = "UNDO";
const REDO = "REDO";
const SET = "SET";
const RESET = "RESET";

type State<T> = {
    past:T[],
    present:T,
    future:T[]
}

type Action<T> = {
    newPresent?:T,
    type:typeof UNDO |typeof REDO|typeof SET | typeof RESET
}

const undoReducer = <T>(state:State<T>,action:Action<T>) =>{
    const {past,present,future} = state
    const {type,newPresent} = action

    switch (action.type){
        case "UNDO":
                if (past.length === 0) return state;

                const previous = past[past.length - 1];

                const newPast = past.slice(0,past.length - 1);
                return {
                    past:newPast,
                    present:previous,
                    future:[present,...future]
                }
        case "REDO":
            if (future.length === 0) return state;

            const next = future[0];
            const newFurture = future.slice(1);

            return {
                past:[...past,present],
                present:next,
                future:newFurture
            }
        case "SET":
            if (newPresent === present) return state;
            return{
                past:[...past,present],
                present:newPresent,
                future:[]
            }
        case "RESET":
            return {
                past:[],
                present:newPresent,
                future:[]
            }
    }

    return state

}



export const useUndo = <T>(initialPresent:T) =>{
    const [state,dispatch] = useReducer(undoReducer,{
        past:[],
        present:initialPresent,
        future:[]
    } as State<T>)


    const undo = useCallback(() =>{dispatch({type:UNDO})},[])

    const redo = useCallback(() => {dispatch({type:REDO})},[])

    const  set = useCallback((newPresent: T) =>{dispatch({type:SET})},[])

    const reset = useCallback((newPresent:T) =>{dispatch({type:RESET})},[])

    return [
       state,
        {set,reset,undo,redo}
    ] as const
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值