首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用redux-observable进行删除操作?

如何使用redux-observable进行删除操作?
EN

Stack Overflow用户
提问于 2017-09-18 23:18:53
回答 1查看 465关注 0票数 0

我正在实现一个对话框,询问用户是否要从DataTable中删除一个项目,如果他同意,epic应该向后端发送一个删除请求,然后更新DataTable的状态,以显示没有删除的项目的列表。我的问题是epic,当我发送OPEN_DELETE_DIALOG操作时,打开模式对话框,redux-observable开始执行DELETE_DATA操作,并向后端发送一个DELETE请求流,甚至没有单击应该发送DELETE_DATA操作的AGREE选项。当用户发送DELETE_DATA操作时,epic应该只发送DELETE请求,我该如何实现?

这是我的对话框组件(在本例中它删除了一个角色):

代码语言:javascript
复制
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)
})

这是我的操作创建者,它是通用的,因此范围可以是用户,角色等:

代码语言:javascript
复制
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())
    }
}

我的史诗是这样的:

代码语言:javascript
复制
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将我的请求发送到后端。我得到的错误是:

代码语言:javascript
复制
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)
EN

回答 1

Stack Overflow用户

发布于 2017-11-08 06:37:58

更改此设置:

代码语言:javascript
复制
<Button onClick={this.props.deleteData(this.props.item)} color="primary">
  Agree
</Button>

至:

代码语言:javascript
复制
<Button onClick={ e => this.props.deleteData(this.props.item)} color="primary">
  Agree
</Button>

否则,您将在每次组件呈现时发送"deleteData“。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46282889

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档