1

I'm new to React and Redux also. I want to remove item from the list so I dispatch an action deleteSelectedItems then I use redux middleware to catch it and show confirm. That looks like below:

Action:

export const deleteSelectedItems = () => {
  return {
    type: ActionTypes.ITEM.DELETE_SELECTED,
    payload: {
      confirm: {
        message: 'Are you sure you want to delete these selected items?'
      }
    }
  }
};

Middleware:

const confirmMiddleware = store => next => action => {
  if (action.payload.confirm) {
    if (confirm(action.payload.confirm.message)) {
      next(action);
    }
  } else {
    next(action);
  }
};

Everything works well. Now, I don't want to use confirm() to show confirm dialog, I want to use my own ConfirmDialog component instead. I found @Dan Abramov solution, that is great. But I am confused how to integrate those together. I want to use confirmMiddleware to dispatch an action that show modal but I don't know how to handle when user click ok or cancel on modal. How can I do that?

Community
  • 1
  • 1
An Nguyen
  • 770
  • 2
  • 12
  • 25

2 Answers2

1

Redux middleware isn't really the right place for UI, it only really works in your existing implementation because window.confirm has magical powers and can stop the thread of execution.

Instead I would recommend dispatching a separate action to open the confirm dialog, e.g. CONFIRM_DELETE_ITEMS which toggles a flag to indicate the dialog should be displayed then dispatch the DELETE_ITEMS action when the dialog confirm button has been clicked.

e.g.

function Root({ dispatch, confirmDeleteItems }) {
    return (
        <div>
            {confirmDeleteItems ? (
                <ConfirmDialog onConfirm={() => dispatch(deleteItems())} onDeny={() = dispatch(hideModal())} />
            ) : null}
            <button onClick={() => dispatch(confirmDeleteItems())}>Delete</button>
        </div>
    )
}
Richard Scarrott
  • 6,638
  • 1
  • 35
  • 46
1

I managed to independently re-invent the modal management technique that Dan describes in that issue, and then pushed it a bit farther. I did a writeup of my approach at Implement a confirm modal using React & Redux.Quoting myself:

I have a central component that is responsible for displaying all currently open dialogs, in the proper layout order (ie, I can have "DialogB" on top of "DialogA", etc). The component that wants to trigger showing the dialog runs an action creator that dispatches a "SHOW_DIALOG" action, with the name of the dialog component in the payload, and arbitrary additional data attached to the action. That data is added to the store, and the dialog managing component will pass that extra data to the dialog component as props when it's rendered.

I've created some generic "picker" dialogs, like ColorPicker and IconPicker. These dialogs know nothing about the rest of my app. They can take some optional bits of data in their props (such as the initially selected color value), and are also looking for a special prop with a name like "onColorSelected". The component that requested the dialog can include the entirety of another action as part of the payload, and when the dialog has its "OK" button clicked on, that new action will be dispatched along with the "return value" of the dialog.

So, in general, my suggestion is to include a plain action object that gets passed along to the dialog, and the dialog can dispatch a copy of the action when it is closed.

Community
  • 1
  • 1
markerikson
  • 63,178
  • 10
  • 141
  • 157