Как сделать действие DELETE с избыточным наблюдаемым?

Я реализую диалоговое окно, которое спрашивает пользователя, хочет ли он удалить элемент из DataTable. Если он согласен, эпик должен отправить запрос DELETE на серверную часть, а затем обновить состояние DataTable, чтобы отобразить список элементов без удаленный. Моя проблема связана с эпопеей, когда я отправляю действие OPEN_DELETE_DIALOG, которое открывает модальный диалог, redux-observable начинает выполнять действие DELETE_DATA и отправляет поток запросов DELETE на серверную часть, даже не нажимая параметр AGREE, который должен отправлять действие DELETE_DATA . Эпопея должна отправлять запрос DELETE только тогда, когда пользователь отправляет действие DELETE_DATA, как я могу этого добиться?

Это мой компонент DIALOG (в данном случае он удаляет роль):

class DeleteDialog extends React.Component {
    render() {
        return (
        <div>
            <MenuItem onClick={_ => {
                console.log(`Edit ${JSON.stringify(this.props.item)}`)
                this.props.openDeleteDialog(this.props.item)
            }}>
            <IconButton aria-label="Edit">
                <DeleteIcon />
            </IconButton>
            <Typography>
                Delete
            </Typography>
            </MenuItem>
            <Dialog open={this.props.open} onRequestClose={this.props.cancelDeleteData}>
            <DialogTitle>{"Delete Alert"}</DialogTitle>
            <DialogContent>
                <DialogContentText>
                Are you sure you want to delete: {this.props.item.name}
                </DialogContentText>
            </DialogContent>
            <DialogActions>
                <Button onClick={this.props.cancelDeleteData} color="primary">
                Cancel
                </Button>
                <Button onClick={this.props.deleteData(this.props.item)} color="primary">
                Agree
                </Button>
            </DialogActions>
            </Dialog>
        </div>
        );
    }
}

const mapStateToProps = state => ({
  open: state.role.delete.open,
})

const mapDispatchToProps = dispatch => ({
  ...deleteDispatchesForScope(scopes.ROLE, dispatch)
})

Это мой создатель действий, он общий, поэтому область действия может быть ПОЛЬЗОВАТЕЛЯМИ, РОЛЯМИ и так далее:

export const actionTypes = {
    OPEN_DELETE_DIALOG: 'OPEN_DELETE_DIALOG',
    DELETE_DATA: 'DELETE_DATA',
    CANCEL_DELETE_DATA: 'CANCEL_DELETE_DATA'
}

export const deleteActionTypesForScope = scope => ({
    OPEN_DELETE_DIALOG: `${scope}_${actionTypes.OPEN_DELETE_DIALOG}`,
    DELETE_DATA: `${scope}_${actionTypes.DELETE_DATA}`,
    CANCEL_DELETE_DATA: `${scope}_${actionTypes.CANCEL_DELETE_DATA}`
})

export const deleteActionForScope = scope => {
    const actionTypes = deleteActionTypesForScope(scope);
    return {
        openDeleteDialog: item => ({
            type: actionTypes.OPEN_DELETE_DIALOG,
            item: item,
            open: true
        }),
        deleteData: item => ({
            type: actionTypes.DELETE_DATA,
            item: item,
            open: false
        }),
        cancelDeleteData: _ => ({
            type: actionTypes.CANCEL_DELETE_DATA,
            item: {},
            open: false
        })
    }
}

export const deleteDispatchesForScope = (scope, dispatch) => {
    const actionCreators = deleteActionForScope(scope);
    return {
        openDeleteDialog: item => dispatch(actionCreators.openDeleteDialog(item)),
        deleteData: item => dispatch(actionCreators.deleteData(item)),
        cancelDeleteData: _ => dispatch(actionCreators.cancelDeleteData())
    }
}

А мой ЭПИК таков:

const deleteRolEpic = (action$, store) => (
    action$.ofType(actionTypes.DELETE_DATA)
        .filter(_ => !store.getState().rol.delete.loading)
        .switchMap(action => {
            let rolpath = 'roles/' + action.item.id;
            return Observable.fromPromise(axios.delete(rolpath))
                .map(response => {
                    history.push('/roles');
                })
        })
)

Где история перенаправляется на путь, где находится моя DataTable ролей, в этом случае. Кроме того, я использую Axios для отправки запросов на серверную часть. Ошибка, которую я получаю, заключается в следующем:

proxyConsole.js:56 Warning: setState(...): Cannot update during an existing state transition (such as within `render` or another component's constructor). Render methods should be a pure function of props and state; constructor side-effects are an anti-pattern, but can be moved to `componentWillMount`.
__stack_frame_overlay_proxy_console__ @ proxyConsole.js:56
printWarning @ warning.js:35
warning @ warning.js:59
getInternalInstanceReadyForUpdate @ ReactUpdateQueue.js:54
enqueueSetState @ ReactUpdateQueue.js:209
./node_modules/react/lib/ReactBaseClasses.js.ReactComponent.setState @ ReactBaseClasses.js:64
onStateChange @ connectAdvanced.js:205
notify @ Subscription.js:26
notifyNestedSubs @ Subscription.js:65
onStateChange @ connectAdvanced.js:202
dispatch @ createStore.js:173
dispatch @ VM4042:2
(anonymous) @ createEpicMiddleware.js:59
dispatch @ VM4042:2
deleteData @ delete-actions.js:38
render @ RolDeleteDialog.js:54
(anonymous) @ ReactCompositeComponent.js:795
measureLifeCyclePerf @ ReactCompositeComponent.js:75
_renderValidatedComponentWithoutOwnerOrContext @ ReactCompositeComponent.js:794
_renderValidatedComponent @ ReactCompositeComponent.js:821
_updateRenderedComponent @ ReactCompositeComponent.js:745
_performComponentUpdate @ ReactCompositeComponent.js:723
updateComponent @ ReactCompositeComponent.js:644
receiveComponent @ ReactCompositeComponent.js:546
receiveComponent @ ReactReconciler.js:124
_updateRenderedComponent @ ReactCompositeComponent.js:753
_performComponentUpdate @ ReactCompositeComponent.js:723
updateComponent @ ReactCompositeComponent.js:644
performUpdateIfNecessary @ ReactCompositeComponent.js:560
performUpdateIfNecessary @ ReactReconciler.js:156
runBatchedUpdates @ ReactUpdates.js:150
perform @ Transaction.js:143
perform @ Transaction.js:143
perform @ ReactUpdates.js:89
flushBatchedUpdates @ ReactUpdates.js:172
closeAll @ Transaction.js:209
perform @ Transaction.js:156
batchedUpdates @ ReactDefaultBatchingStrategy.js:62
batchedUpdates @ ReactUpdates.js:97
dispatchEvent @ ReactEventListener.js:147
proxyConsole.js:56 Warning: Failed prop type: Invalid prop `onClick` of type `object` supplied to `ButtonBase`, expected `function`.
    in ButtonBase (created by withStyles(ButtonBase))
    in withStyles(ButtonBase) (created by Button)
    in Button (created by withStyles(Button))
    in withStyles(Button) (at RolDeleteDialog.js:54)
    in div (created by DialogActions)
    in div (created by DialogActions)
    in DialogActions (created by withStyles(DialogActions))
    in withStyles(DialogActions) (at RolDeleteDialog.js:50)
    in div (created by Paper)
    in Paper (created by withStyles(Paper))
    in withStyles(Paper) (created by Dialog)
    in Transition (created by Fade)
    in Fade (created by withTheme(Fade))
    in withTheme(Fade) (created by Dialog)
    in div (created by Modal)
__stack_frame_overlay_proxy_console__ @ proxyConsole.js:56
printWarning @ warning.js:35
warning @ warning.js:59
checkReactTypeSpec @ checkReactTypeSpec.js:80
validatePropTypes @ ReactElementValidator.js:162
createElement @ ReactElementValidator.js:216
createEagerElementUtil @ createEagerElementUtil.js:31
(anonymous) @ createEagerFactory.js:18
render @ withStyles.js:345
(anonymous) @ ReactCompositeComponent.js:795
measureLifeCyclePerf @ ReactCompositeComponent.js:75
_renderValidatedComponentWithoutOwnerOrContext @ ReactCompositeComponent.js:794
_renderValidatedComponent @ ReactCompositeComponent.js:821
performInitialMount @ ReactCompositeComponent.js:361
mountComponent @ ReactCompositeComponent.js:257
mountComponent @ ReactReconciler.js:45
performInitialMount @ ReactCompositeComponent.js:370
mountComponent @ ReactCompositeComponent.js:257
mountComponent @ ReactReconciler.js:45
performInitialMount @ ReactCompositeComponent.js:370
mountComponent @ ReactCompositeComponent.js:257
mountComponent @ ReactReconciler.js:45
mountChildren @ ReactMultiChild.js:236
_createInitialChildren @ ReactDOMComponent.js:703
mountComponent @ ReactDOMComponent.js:522
mountComponent @ ReactReconciler.js:45
mountChildren @ ReactMultiChild.js:236
_createInitialChildren @ ReactDOMComponent.js:703
mountComponent @ ReactDOMComponent.js:522
mountComponent @ ReactReconciler.js:45
performInitialMount @ ReactCompositeComponent.js:370
mountComponent @ ReactCompositeComponent.js:257
mountComponent @ ReactReconciler.js:45
performInitialMount @ ReactCompositeComponent.js:370
mountComponent @ ReactCompositeComponent.js:257
mountComponent @ ReactReconciler.js:45
mountChildren @ ReactMultiChild.js:236
_createInitialChildren @ ReactDOMComponent.js:703
mountComponent @ ReactDOMComponent.js:522
mountComponent @ ReactReconciler.js:45
performInitialMount @ ReactCompositeComponent.js:370
mountComponent @ ReactCompositeComponent.js:257
mountComponent @ ReactReconciler.js:45
performInitialMount @ ReactCompositeComponent.js:370
mountComponent @ ReactCompositeComponent.js:257
mountComponent @ ReactReconciler.js:45
performInitialMount @ ReactCompositeComponent.js:370
mountComponent @ ReactCompositeComponent.js:257
mountComponent @ ReactReconciler.js:45
performInitialMount @ ReactCompositeComponent.js:370
mountComponent @ ReactCompositeComponent.js:257
mountComponent @ ReactReconciler.js:45
performInitialMount @ ReactCompositeComponent.js:370
mountComponent @ ReactCompositeComponent.js:257
mountComponent @ ReactReconciler.js:45
mountChildren @ ReactMultiChild.js:236
_createInitialChildren @ ReactDOMComponent.js:703
mountComponent @ ReactDOMComponent.js:522
mountComponent @ ReactReconciler.js:45
performInitialMount @ ReactCompositeComponent.js:370
mountComponent @ ReactCompositeComponent.js:257
mountComponent @ ReactReconciler.js:45
mountComponentIntoNode @ ReactMount.js:104
perform @ Transaction.js:143
batchedMountComponentIntoNode @ ReactMount.js:126
batchedUpdates @ ReactDefaultBatchingStrategy.js:60
batchedUpdates @ ReactUpdates.js:97
_renderNewRootComponent @ ReactMount.js:319
_renderSubtreeIntoContainer @ ReactMount.js:401
renderSubtreeIntoContainer @ ReactMount.js:342
renderLayer @ Portal.js:130
componentDidMount @ Portal.js:70
(anonymous) @ ReactCompositeComponent.js:264
measureLifeCyclePerf @ ReactCompositeComponent.js:75
(anonymous) @ ReactCompositeComponent.js:263
notifyAll @ CallbackQueue.js:76
close @ ReactReconcileTransaction.js:80
closeAll @ Transaction.js:209
perform @ Transaction.js:156
perform @ Transaction.js:143
perform @ ReactUpdates.js:89
flushBatchedUpdates @ ReactUpdates.js:172
closeAll @ Transaction.js:209
perform @ Transaction.js:156
batchedUpdates @ ReactDefaultBatchingStrategy.js:62
batchedUpdates @ ReactUpdates.js:97
dispatchEvent @ ReactEventListener.js:147
invariant.js:44 Uncaught Error: Expected onClick listener to be a function, instead got type object
    at invariant (invariant.js:44)
    at Object.putListener (EventPluginHub.js:132)
    at Object.putListener (ReactDOMComponent.js:177)
    at CallbackQueue.notifyAll (CallbackQueue.js:76)
    at ReactReconcileTransaction.close (ReactReconcileTransaction.js:80)
    at ReactReconcileTransaction.closeAll (Transaction.js:209)
    at ReactReconcileTransaction.perform (Transaction.js:156)
    at batchedMountComponentIntoNode (ReactMount.js:126)
    at Object.batchedUpdates (ReactDefaultBatchingStrategy.js:60)
    at Object.batchedUpdates (ReactUpdates.js:97)
    at Object._renderNewRootComponent (ReactMount.js:319)
    at Object._renderSubtreeIntoContainer (ReactMount.js:401)
    at Object.renderSubtreeIntoContainer [as unstable_renderSubtreeIntoContainer] (ReactMount.js:342)
    at Portal.renderLayer (Portal.js:130)
    at Portal.componentDidMount (Portal.js:70)
    at ReactCompositeComponent.js:264
    at measureLifeCyclePerf (ReactCompositeComponent.js:75)
    at ReactCompositeComponent.js:263
    at CallbackQueue.notifyAll (CallbackQueue.js:76)
    at ReactReconcileTransaction.close (ReactReconcileTransaction.js:80)
    at ReactReconcileTransaction.closeAll (Transaction.js:209)
    at ReactReconcileTransaction.perform (Transaction.js:156)
    at ReactUpdatesFlushTransaction.perform (Transaction.js:143)
    at ReactUpdatesFlushTransaction.perform (ReactUpdates.js:89)
    at Object.flushBatchedUpdates (ReactUpdates.js:172)
    at ReactDefaultBatchingStrategyTransaction.closeAll (Transaction.js:209)
    at ReactDefaultBatchingStrategyTransaction.perform (Transaction.js:156)
    at Object.batchedUpdates (ReactDefaultBatchingStrategy.js:62)
    at Object.batchedUpdates (ReactUpdates.js:97)
    at dispatchEvent (ReactEventListener.js:147)

person sgaseretto    schedule 18.09.2017    source источник


Ответы (1)


Измените это:

<Button onClick={this.props.deleteData(this.props.item)} color="primary">
  Agree
</Button>

To:

<Button onClick={ e => this.props.deleteData(this.props.item)} color="primary">
  Agree
</Button>

В противном случае вы будете отправлять «deleteData» каждый раз при рендеринге компонента.

person msolvaag    schedule 07.11.2017