我正在实现一个Dialog,询问用户是否要从DataTable中删除一个Item,如果他同意,一个epic应该向后端发送一个DELETE请求,然后更新DataTable的状态以显示该列表没有删除的项目。我的问题在于epic,当我调度打开模态对话框的OPEN_DELETE_DIALOG操作时,redux-observable开始执行DELETE_DATA操作并向后端发送DELETE请求流,即使没有单击应该调度DELETE_DATA操作的AGREE选项也是如此。 史诗应该只在用户调度DELETE_DATA动作时发送DELETE请求,我该如何实现呢?
这是我的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)
})
这是我的动作创作者,它是通用的,因此范围可以是USERS,ROLES等:
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())
}
}
我的EPIC是这样的:
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)
答案 0 :(得分:0)
改变这个:
out = HSD.test(model, "virus", group = FALSE)
print(out$comparison)
difference pvalue signif. LCL UCL
cc - fc 11.5333333 0.0686 . -0.8663365 23.9330031
cc - ff -11.9333333 0.0592 . -24.3330031 0.4663365
cc - oo -12.5000000 0.0482 * -24.8996698 -0.1003302
fc - ff -23.4666667 0.0014 ** -35.8663365 -11.0669969
fc - oo -24.0333333 0.0012 ** -36.4330031 -11.6336635
ff - oo -0.5666667 0.9988 -12.9663365 11.8330031
致:
<Button onClick={this.props.deleteData(this.props.item)} color="primary">
Agree
</Button>
否则,每次组件渲染时,您都会发送“deleteData”。