I try to build a generic confirm component with redux and native promise. I read Dan Abramovs solution here: How can I display a modal dialog in Redux that performs asynchronous actions? but i am looking for a more generic appoach. Basically i want to do this:
confirm({
  type: 'warning',
  title: 'Are you sure?',
  description: 'Would you like to do this action?',
  confirmLabel: 'Yes',
  abortLabel: 'Abort'
})
.then(() => {
  // do something after promise is resolved
})
The confirm method basically opens the modal and returns a promise. Inside the promise i subscribe my redux store, listen for state changes and resolve or reject the promise:
export const confirm = function(settings) {
  // first dispatch openConfirmModal with given props
  store.dispatch(
    openConfirmModal({
      ...settings
    })
  );
  // return a promise that subscribes to redux store
  // see: http://redux.js.org/docs/api/Store.html#subscribe
  // on stateChanges check for resolved/rejected
  // if resolved or rejected:
  // - dispatch closeConfirmModal
  // - resolve or reject the promise
  // - unsubscribe to store
  return new Promise((resolve, reject) => {
    function handleStateChange() {
      let newState = store.getState();
      if (newState.confirmModal.resolved) {
        store.dispatch(closeConfirmModal());
        resolve();
        unsubscribe();
      }
      if (newState.confirmModal.rejected) {
        store.dispatch(closeConfirmModal());
        reject();
        unsubscribe();
      }
    }
    let unsubscribe = store.subscribe(handleStateChange);
  })
}
My confirm component is connected to redux store and is included once in some kind of layout component - so it is useable on all routes in the app:
class ConfirmModal extends Component {
  constructor(props) {
    super(props)
  }
  confirm() {
    this.props.dispatch(resolveConfirmModal());
  }
  abort() {
    this.props.dispatch(rejectConfirmModal());
  }
  render() {
    // my modal window 
  }
}
export default connect(
  state => ({
    confirmModal: state.confirmModal
  })
)(ConfirmModal);
Reducer/Action looks like this:
export const openConfirmModal = (settings) => {
  return {
    type: 'OPEN_CONFIRM_MODAL',
    settings
  };
};
export const resolveConfirmModal = () => {
  return {
    type: 'RESOLVE_CONFIRM_MODAL'
  };
};
export const rejectConfirmModal = () => {
  return {
    type: 'REJECT_CONFIRM_MODAL'
  };
};
export const closeConfirmModal = () => {
  return {
    type: 'CLOSE_CONFIRM_MODAL'
  };
};
const initialState = {
  open: false,
  type: 'info',
  title: 'Are you sure?',
  description: 'Are you sure you want to do this action?',
  confirmLabel: 'Yes',
  abortLabel: 'Abort',
};
export const ConfirmModalReducer = (state = initialState, action) => {
  switch (action.type) {
    case 'OPEN_CONFIRM_MODAL':
      return { ...action.settings, open: true };
    case 'RESOLVE_CONFIRM_MODAL':
      return { ...state, resolved: true };
    case 'REJECT_CONFIRM_MODAL':
      return { ...state, rejected: true };
    case 'CLOSE_CONFIRM_MODAL':
      return initialState;
    default:
      return state;
  }
};
The redux part is working. My confirm window can be open/closed and renders depending on my options. But how i can define a promise in my confirm method that can be resolved in my component? How i get everything connected?
Found a working Solution!
Found a solution that is pretty much what i was looking for:
- The modal properties are driven by my Redux state
- The modal component is included once AND it lives inside my applicition not as a different rendered app like here:http://blog.arkency.com/2015/04/beautiful-confirm-window-with-react/
- The confirm method returns a native promise that is resolved/rejected driven by Redux state
What do you think?
 
     
     
     
     
    