redux-thunk:暂停组件执行,直到 Action Creator 完成

Posted

技术标签:

【中文标题】redux-thunk:暂停组件执行,直到 Action Creator 完成【英文标题】:redux-thunk: Pause Component Execution Until Action Creator Completes 【发布时间】:2016-10-30 02:25:17 【问题描述】:

我已经为这个问题苦苦挣扎了好几个星期了。我终于认输并寻求帮助,因为我显然没有做对。我有一个使用 redux 和 redux-thunk 的 React.js 应用程序。我只是想让我的组件容器启动数据加载,但在数据从获取请求返回之前不渲染。似乎很简单,我知道。这是我所做的:

容器组件

'use strict';
import React,  Component  from 'react';
import  connect  from 'react-redux';
import  fetchActivePlayer  from '../actions/index';
import PlayerDetails from '../components/players/player-detail';
import Spinner from '../components/common/spinner/index';
import store from '../store';

export default class PlayerDetailContainer extends Component 
    constructor(props) 
        super(props);
    

    componentWillMount() 
        this.props.fetchActivePlayer(this.props.params.player_slug)
    

    render() 
        if (!this.props.activePlayer.activePlayer) 
            return (
                <Spinner text="Loading..." style="fa fa-spinner fa-spin" />
            );
        

        return (
            <PlayerDetails 
                player= this.props.activePlayer.activePlayer  
            />
        );
    


function mapStateToProps(state) 
    return 
        activePlayer: state.activePlayer
    

export default connect(mapStateToProps,  fetchActivePlayer )(PlayerDetailContainer);

动作创建者

export function fetchActivePlayer(slug) 
    return (dispatch, getState) => 
        return axios.get(`$ROOT_URL/players/$slug`)
        .then(response => 
            dispatch(
                type: FETCH_ACTIVE_PLAYER,
                payload: response
            )
        )
        .catch(err => 
            console.error("Failure: ", err);
        );    
    ;

商店

'use strict';
import React from 'react';
import  browserHistory  from 'react-router';
import  createStore, applyMiddleware  from 'redux';
import  routerMiddleware  from 'react-router-redux';
import thunk from 'redux-thunk';
import promise from 'redux-promise';
import reducers from './components/reducers/index';

const createStoreWithMiddleware = applyMiddleware(
    thunk,
    promise,
    routerMiddleware(browserHistory)
) (createStore);
export default createStoreWithMiddleware(reducers);

路线

export default (
<Route path="/" component= App >
        <IndexRoute component= HomePage  />
        <Route path="players/:player_slug" component= PlayerContainer  />
        <Route path="/:player_slug" component= PlayerContainer  />
    </Route>
);

以下是我用于所有内容的版本: 反应 = 0.14.7 反应减少 = 4.4.1 redux-thunk = 0.5.3

当我运行它时,我没有收到任何错误,但很明显我的动作创建者正在触发,但我的组件容器继续而不是等待创建者完成。就像我说的那样,我确定我一定错过了一些非常简单的东西,但我似乎无法弄清楚那是什么。

提前谢谢你。任何帮助将不胜感激。

【问题讨论】:

您的意思是您的微调器从不显示?还是只显示您的微调器? 您能否在问题中包含您的减速器,以便我们查看您的状态形状? 另外,为了澄清一些语言,你永远不要暂停组件的执行。这就像暂停你的大脑。 UI 就像生活一样,只是一个恒定的流,你只是根据当前状态呈现不同的东西。 谢谢@azium。我的微调器确实显示。我试图让我的组件暂停加载,直到我的数据返回,我现在意识到这是不可能的。我显然误解了 react-thunk 组件示例。 【参考方案1】:
    您在 componentWillMount 中的操作(获取)是异步的,组件不会等待。 通常当您获取一些数据时,您想了解获取过程的状态。比如“isfetching”是为了显示加载器,成功和失败是为了显示错误。 您可以使用这些状态来不加载/安装/启动组件,直到 Action Creator 完成。

因此,你应该像这样组织你的 redux 部分:

状态

activePlayer:
    data:data,
    isFetching: true/false,
    error:""
    

动作

export const fetchActivePlayer = slug => dispatch =>
    dispatch(
        type: 'FETCH_ACTIVE_PLAYER_REQUEST',
        isFetching:true,
        error:null
    );

    return axios.get(`$ROOT_URL/players/$slug`)
    .then(response => 
        dispatch(
            type: 'FETCH_ACTIVE_PLAYER_SUCCESS',
            isFetching:false,
            payload: response
        );
    )
    .catch(err => 
        dispatch(
            type: 'FETCH_ACTIVE_PLAYER_FAILURE',
            isFetching:false,
            error:err
        );
        console.error("Failure: ", err);
    );

;

减速器

const initialState = data:null,isFetching: false,error:null;
export const actionPlayer = (state = initialState, action)=>
    switch (action.type) 
        case 'FETCH_ACTIVE_PLAYER_REQUEST':
        case 'FETCH_ACTIVE_PLAYER_FAILURE':
        return  ...state, isFetching: action.isFetching, error: action.error ;

        case 'FETCH_ACTIVE_PLAYER_SUCCESS':
        return  ...state, data: action.payload, isFetching: action.isFetching,
                 error: null ;
        default:return state;

    
;

那么您的组件可能看起来像这样(硬代码)

class PlayerDetailContainer extends Component 
    componentWillMount() 
        this.props.fetchActivePlayer(this.props.params.player_slug)
    
    render() 
        if (this.props.isFetching) 
            return <Spinner text="Loading..." style="fa fa-spinner fa-spin" />

        else if (this.props.error) 
            return <div>ERROR this.props.error</div>
        else 
            return <PlayerDetails  player= this.props.data   />
        
    

const mapStateToProps = state =>(
        isFetching: state.activePlayer.isFetching,
        data: state.activePlayer.data,
        error: state.activePlayer.error,
)

我不知道你的应用是什么样子的。这个例子的目的是说明方法。

【讨论】:

谢谢 Utro。我会试试这个并回复你。

以上是关于redux-thunk:暂停组件执行,直到 Action Creator 完成的主要内容,如果未能解决你的问题,请参考以下文章

暂停执行,直到从 tkinter 窗口收到用户输入

暂停函数执行流程,直到 ajax 请求完成

PHP,暂停脚本执行,直到另一个正在运行的脚本发出事件信号?

如何暂停整个程序的执行,直到在 JAVA 中按下按钮?

暂停功能,直到承诺解决[重复]

Unity:如何暂停执行直到函数终止,以便不跳过任何帧