Last active
December 14, 2023 08:52
-
-
Save johanquiroga/cbbfc0da2e9f11d2dbfd15acc4db6fc0 to your computer and use it in GitHub Desktop.
Undo/Redo capability for any reducer using react hook `useReducer`
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useReducer } from 'react'; | |
const useUndoReducer = (reducer, initialState) => { | |
const undoState = { | |
past: [], | |
present: initialState, | |
future: [] | |
}; | |
const undoReducer = (state, action) => { | |
const newPresent = reducer(state.present, action); | |
if (action.type === useUndoReducer.types.undo) { | |
const [newPresent, ...past] = state.past; | |
return { | |
past, | |
present: newPresent, | |
future: [state.present, ...state.future] | |
}; | |
} | |
if (action.type === useUndoReducer.types.redo) { | |
const [newPresent, ...future] = state.future; | |
return { | |
past: [state.present, ...state.past], | |
present: newPresent, | |
future | |
}; | |
} | |
return { | |
past: [state.present, ...state.past], | |
present: newPresent, | |
future: [] | |
}; | |
}; | |
return useReducer(undoReducer, undoState); | |
}; | |
useUndoReducer.types = { | |
undo: 'UNDO', | |
redo: 'REDO' | |
}; | |
export default useUndoReducer; | |
// Example | |
/* import React, { useReducer } from "react"; | |
import useUndoReducer from "./useUndoReducer"; | |
const initialState = {} | |
const reducer = (state = initialState, action) => { | |
// Your reducer | |
return state; | |
}; | |
const YourComponent = (props) => { | |
const [state, dispatch] = useUndoReducer(reducer, initialState); | |
// Some actions | |
const someAction = useCallback( | |
(payload) => { | |
dispatch({ | |
type: 'SOME_ACTION', | |
payload, | |
}); | |
}, | |
[dispatch] | |
); | |
// Undo/Redo actions | |
const undo = useCallback(() => { | |
dispatch({ type: useUndoReducer.types.undo }); | |
}, [dispatch]); | |
const redo = useCallback(() => { | |
dispatch({ type: useUndoReducer.types.redo }); | |
}, [dispatch]); | |
// render or do something something | |
// ... | |
} | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment