代码之家  ›  专栏  ›  技术社区  ›  lampShadesDrifter

在进行异步调用时,从同一个thunk调度的多个操作之间似乎没有更新组件?

  •  0
  • lampShadesDrifter  · 技术社区  · 6 年前

    使用react native,当从mapdispatchtoprops调用时,组件是否在从同一thunk调度的多个操作之间不更新?询问,因为我的用例是:尝试从thunk操作创建者执行异步API请求,但是设置和取消设置其间的isfetching标志,以便在屏幕上显示加载微调器覆盖,如下所示:

    // ComponentPresenter.js
    export default class SigninScreenPresenter extends React.Component {
        constructor(props) {
            super(props);
        }
        componentDidUpdate() {
            console.log(`isFetching=${this.props.isFetching}`)
        }
        handlePress = () => {
            this.props.stateCallback()
        }
        render() {
            return(
            <SomeOtherStuff onPress={this.handlePress.bind(this)}/>
            <Spinner visible={this.props.isFetching} textContent={"Loading..."} textStyle={{color: '#FFF'}} />
            )
        }
    }
    
    
    
    // ComponentContainer.js
    const mapStateToProps = (state, ownProps) => {
        // checking state changes
        console.log(`mapping state to props: state.session.isFetching=${state.session.isFetching}`)
        return {
            isFetching: state.session.isFetching,
            ownProps: ownProps
        }
    }
    
    const mapDispatchToProps = (dispatch, ownProps) => {
      return {
          stateCallback: () => {
              dispatch(apiRequestThunk())
            }
      }
    }
    
    const ComponentContainer = connect(
      mapStateToProps,
      mapDispatchToProps
    )(ComponentPresenter)
    
    export default ComponentContainer
    
    
    
    // actions/index.js
    .....
    export function setFetchingFlag() {
        return {type: SET_FETCHING}
    }
    export function unsetFetchingFlag() {
        return {type: UNSET_FETCHING}
    }
    export function apiRequestThunk() {
        return function (dispatch) {
            dispatch(setFetchingFlag())
            fetch(...making some REST request...)
                .then(
                    (res) => {dispatch(someSuccessAction())}, 
                    (error) => {dispatch(someFailureAction())})
            dispatch(unsetFetchingFlag())
        }
    }
    .....
    
    
    
    // reducers/index.js
    .....
    const sessionReducer = (state=initialState.session, action) => {
        switch (action.type) {
            case FLAG_API_REQUEST:
                console.log('fetching API request')
                return Object.assign({}, state, {isFetching: true})
            case UNFLAG_API_REQUEST:
                console.log('done fetching API request')
                return Object.assign({}, state, {isFetching: false})
            default:
                return state
        }
    }
    .....
    const rootReducer = combineReducers({
        session: sessionReducer,
        otherStateFields: otherReducers,
        .....
    })
    export default rootReducer
    

    我在演示者组件中触发handlePress()时看到的控制台输出是

    [14:49:03] fetching API request   (from reducers)
    [14:49:03] mapping state to props: state.session.isFetching=true   (from container)
    [14:49:03] done fetching API request    (from reducer)
    [14:49:03] mapping state to props: state.session.isFetching=false    (from container)
    [14:49:03] In component presenter: isFetching=false    (from presenter (I would expect another one before this with isFetching=True))
    

    旋转器从不渲染。

    注意,在组件展示器中没有输出“isfetching=true”(就好像它从不从映射到状态的过程中读取,即使输出表明它正在被调用)。这使得组件看起来不像是在演示者组件中调用的mapDispatchToCallback函数之后才使用mapStateToProps值进行精确更新。 完成 正在执行。

    这里还有什么问题吗?有没有更“最佳实践”的方法来做到这一点?新的thunk和redux,所以任何调试建议都会受到赞赏。

    1 回复  |  直到 6 年前
        1
  •  1
  •   lampShadesDrifter    6 年前

    我的建议是打电话 dispatch(unsetFetchingFlag()) 一旦异步请求被解析/拒绝。在这里启动加载程序,然后发送 异步的 请求。这很好。然而, 在不等待解决请求的情况下,您正在取消设置加载程序 . 我相信这就是问题所在。看看这个解决方案。

    export function apiRequestThunk() {
        return dispatch => {
            // Start the loader
            dispatch(setFetchingFlag());
    
            // Send the async request
            fetch(...making some REST request...)
                .then(res => {
                  // The request has been resolved. So stop the loader. 
                  dispatch(someSuccessAction());
                  dispatch(unsetFetchingFlag());
                }) 
                .catch(error => {
                  // An error has occurred. So 
                  // 1. Stop the loader. 
                  // 2. Display the error, if require
                  dispatch(unsetFetchingFlag());
                  dispatch(someFailureAction());
                });
        }
    }
    

    使用异步/等待

    export function apiRequestThunk() {
      return async dispatch => {
          // Start the loader
          dispatch(setFetchingFlag());
    
          try {
            // Send the async request
            const response= await fetch(...making some REST request...);
    
            // Once the request gets resolved, stop the loader. 
            // If any error occur in the request, then the error will be caught in the 'catch' block
            dispatch(someSuccessAction());
            dispatch(unsetFetchingFlag());
          }
          catch(error) {
            // An error has occurred. So 
            // 1. Stop the loader. 
            // 2. Display the error, if required
            dispatch(unsetFetchingFlag());
            dispatch(someFailureAction());
          }
      }
    } 
    

    也不需要绑定 onPress 因为你已经在使用箭头函数了。 <SomeOtherStuff onPress={this.handlePress}/>