Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

withUndoRedo and store with side-effects #95

Open
marcindz88 opened this issue Sep 14, 2024 · 5 comments
Open

withUndoRedo and store with side-effects #95

marcindz88 opened this issue Sep 14, 2024 · 5 comments

Comments

@marcindz88
Copy link
Contributor

Hi,
I have a use case where I am using the undo-redo feature, but when I add an entity I also execute a side-effect (e.g. HTTP request). I am now considering how to implement the reverse side effect when undoing the state (which is an effect for the deletion of an entity).

My idea is that if I could specify a reverse action in an action, then this reverse action could be called by the undo-redo when undoing the state. This however would require undo-redo to register a stack of previous and future actions (like a list of diffs) instead of holding copies of the state and to be able to observe when an action is called.

@rainerhahnekamp
Copy link
Collaborator

Hey, so how would that look like? Could you come with an example pseudo example?

@marcindz88
Copy link
Contributor Author

@rainerhahnekamp I am trying to make this work so far I have sth like this:

withUndoRedo({
  actionsMap: {
    addEntity: 'removeEntity',
    removeEntity: 'addEntity',
    updateEntity: {
      actionName: 'updateEntity',
      payloadFn: ({ oldEntity, entity }) => ({ oldEntity: entity, entity: oldEntity }),
    },
  },
}),

If the payload is the same type you can provide just a reversed action name, or provide a payload mapper, if it has other payload types you have to provide the mapper.

Then undo-redo listens when the method (action) is called and adds it to the stack, when we call undo() then we take last action from the stack, use the actionsMap to figure out reverse one and run in on the store

@marcindz88
Copy link
Contributor Author

@rainerhahnekamp
I wanted to get info when the action is called by implementing something like this:

withHooks({
  onInit(store) {
    Object.keys(normalized.actionsMap).forEach((action: keyof Input['methods']) => {
      const originalActionCreator = (store as Record<keyof Input['methods'], BasicActionCreator>)[action];
      (store as Record<keyof Input['methods'], BasicActionCreator>)[action] = (payload: Payload) => {
        originalActionCreator(payload);
        if (!skip) {
          undoStack.push({ actionName: action as string, payload });
          redoStack.splice(0);
        }
      };
    });
  },
})

But the replaced fn is not called for some reason.

Do you have some other idea how this could be implemented?

@marcindz88
Copy link
Contributor Author

Ah, i figured it out, these functions are kind of immutable and are overridden later. I have a working solution that overrides the action creator functions with the use of withMethods, but this undoRedo feature is very different than the one in the library. Would you be interested in adding it here as a second undoRedo variant or should I keep it to myself?

@rainerhahnekamp
Copy link
Collaborator

I'd be careful and not patch the internals that much. We can keep this issue opened for 60 days and check if other developers require it as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants