How to access state from inside mapDispatchToProps

2019-07-19 04:54发布

问题:

Need to dispatch an action based on state or presentaional component's props.

const mapDispatchToProps = (dispatch) => {
  return {
    onClick: () => {
       if (state.someValue || this.props.someValue){
          dispatch({type: DO_SOMETHING})   
       }
    }

  }
} 

and this action is supposed to be intercepted by redux-saga to do some remote fetching tasks, so I can't move this condition into reducer like:

const reducer = (state, action) => {
    switch (action.type){
       case DO_SOMETHING:
          if(state.someValue){
             return {...state, //do something}
             //I need to fetch some api here, so this won't be a valid way 
          }
    }
}

Can a dispatch fired from inside reducer? so that the new fired dispatch can be intercepted by redux-saga.

回答1:

A dispatch cannot be fired from a reducer

If checking state must be done by the component, then use the third parameter of connect, aka mergeProps:

const mapStateToProps = state => ({
    someValue: // ...,
    // ...
})

const mapDispatchToProps = dispatch => {
  return {
    onClick: () => dispatch({type: DO_SOMETHING}),
    // ...
  }
}

const mergeProps = (stateProps, dispatchProps, ownProps) => {
    const onClick = () => {
        if (stateProps.someValue) {
            dispatchProps.onClick();
        }
    }

    return ({
        ...stateProps,
        ...dispatchProps,
        onClick
    })
}

export default connect(mapStateToProps, mapDispatchToProps, mergeProps)(MyComponent)

If checking state does not need to be part of the component, then check the state in a saga task:

component:

const mapDispatchToProps = dispatch => {
  return {
    onClick: () => dispatch({type: MAYBE_DO_SOMETHING}),
    // ...
  }
}

saga:

function* onMaybeDoSomething(action) {
    const someValue = yield select(getSomeValue)

    if (someValue) {
        yield put({ type: DO_SOMETHING })
    }
}

export default function* () {
    takeLatest(MAYBE_DO_SOMETHING, onMaybeDoSomething)
}