charkour / zundo

🍜 undo/redo middleware for zustand. <700 bytes
https://codesandbox.io/s/zundo-2dom9
MIT License
597 stars 19 forks source link

onUndo: Is there a way to call a function when undoing the state? #151

Closed algokun closed 6 months ago

algokun commented 8 months ago

Hey there! Thanks a lot for making this. I've been searching for something like this and I finally found exactly what I'm looking for.

For context - I'm building a forms product similar to typeform and now I'm introducing undo/redo functionality to every user operation. I started using this package for my product and it's just very easy to set up, thanks again.

I have a special block and when it gets removed, I call an API that'll not just remove the block in dB and it also removes yet another doc in a different collection.

Whenever we're bringing the removed block again, I need to call a different API and it would be helpful if I have a callback onUndo with the latest state update that you're pushing so that I can handle the backend.

Let me know if there's a better way to achieve this 🤔

charkour commented 8 months ago

Hey, thanks for making the issue and I'm happy to hear it's initially solving your problem.

Your use case makes sense, and I can spend some time this weekend seeing if it's possible to achieve an onUndo callback with the current API.

If not, we can add some callbacks that fire like we have for onSave.

To help me get started, please create a code sandbox with your best attempt of solving the problem! Thank you.

pstrassmann commented 7 months ago

@algokun Just to check, is something vaguely like this sufficient for your use case? Where myCallback is the callback you need called on every undo action? At the time of undo/redo click, do you have access to the data you would want passed to myCallback?


export const UndoButton = () => {

   const { undo } = useStore.temporal.getState()

   const undoStateHistory = async () => {
     try {
        undo()
        await myCallback()
     } catch (error) {
        console.error(error)
     }

   }

   return <button onClick={undoStateHistory}>Undo</button>
}
algokun commented 6 months ago

Hey folks, sorry for the late response. I updated few things in my backend to achieve the same. I have an API that gets called every 500ms (debounced) to save the changes. When making the change, I'm comparing the prev and updated and calling the API to indicate that the special block is deleted. Just wanted to keep front-end simple.

algokun commented 6 months ago

@algokun Just to check, is something vaguely like this sufficient for your use case? Where myCallback is the callback you need called on every undo action? At the time of undo/redo click, do you have access to the data you would want passed to myCallback?

export const UndoButton = () => {

   const { undo } = useStore.temporal.getState()

   const undoStateHistory = async () => {
     try {
        undo()
        await myCallback()
     } catch (error) {
        console.error(error)
     }

   }

   return <button onClick={undoStateHistory}>Undo</button>
}

Thanks a lot, this is useful. Haven't thought about it this way.