美文网首页
[原创]React Hooks UseReducer 实现撤销前

[原创]React Hooks UseReducer 实现撤销前

作者: luokaiii | 来源:发表于2020-03-26 13:54 被阅读0次

    示例

    示例

    直接上代码

    1. reducer.js

    import React from "react";
    import _originalUpdate from "immutability-helper";
    
    export const TestDispatch = React.createContext(null);
    
    export const Actions = {
      /**
       * 修改数据
       */
      CHANGE: "CHANGE",
      /**
       * 撤销数据
       */
      UNDO: "UNDO",
      /**
       * 恢复数据
       */
      REDO: "REDO"
    };
    
    const originalUpdate = (state, spec) => {
      // _originalUpdate 在不改变原数据的情况下更新数据
      const newState = _originalUpdate(state, spec);
      if (newState.present) {
        window.localStorage.setItem("present", newState.present);
      }
      return newState;
    };
    
    const update = (state, spec) => {
      const newPresent = originalUpdate(state.present, Object.assign({}, spec));
      return originalUpdate(state, {
        past: { $push: [state.present] },
        present: { $set: newPresent },
        future: { $set: [] }
      });
    };
    
    const undo = state => {
      const lastIndex = state.past.length - 1;
      const last = state.past[lastIndex];
      const present = state.present;
      return originalUpdate(state, {
        past: { $splice: [[lastIndex, 1]] },
        present: { $set: last },
        future: { $unshift: [present] }
      });
    };
    
    const redo = state => {
      const firstFuture = state.future[0];
      const present = state.present;
      return originalUpdate(state, {
        past: { $push: [present] },
        present: { $set: firstFuture },
        future: { $splice: [[0, 1]] }
      });
    };
    
    
    export default (state, { type, payload }) => {
      switch (type) {
        case Actions.CHANGE: {
          return update(state, { value: { $set: payload.value } });
        }
        case Actions.UNDO: {
          return undo(state);
        }
        case Actions.REDO: {
          return redo(state);
        }
        default:
          throw new Error();
      }
    };
    

    2. App.js

    import React, { useReducer } from "react";
    import reducer, { Actions, TestDispatch } from "./reducer";
    
    import "./App.css";
    
    export default () => {
      const [state, dispatch] = useReducer(reducer, {
        past: [],
        present: {},
        future: []
      });
      const item = state.present;
    
      const handleUndo = () => {
        dispatch({
          type: Actions.UNDO
        });
      };
    
      const handleRedo = () => {
        dispatch({
          type: Actions.REDO
        });
      };
    
      const handleChange = e => {
        dispatch({
          type: Actions.CHANGE,
          payload: {
            value: e.target.value
          }
        });
      };
    
      return (
        <TestDispatch.Provider value={dispatch}>
          <div className="App">
            <button onClick={handleUndo} disabled={state.past.length === 0}>
              撤销
            </button>
            <button onClick={handleRedo} disabled={state.future.length === 0}>
              前进
            </button>
            <div>
              <input value={item.value || ""} onChange={handleChange} />
            </div>
          </div>
        </TestDispatch.Provider>
      );
    };
    

    相关文章

      网友评论

          本文标题:[原创]React Hooks UseReducer 实现撤销前

          本文链接:https://www.haomeiwen.com/subject/nwqcuhtx.html