簡體   English   中英

redux-thunk:暫停組件執行直到Action Creator完成

[英]redux-thunk: Pause Component Execution Until Action Creator Completes

幾個星期以來,我一直在努力解決這個問題。 我終於放棄了並在此尋求幫助,因為我顯然沒有做正確的事情。 我有一個使用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>
);

以下是我用於所有內容的版本:react = 0.14.7 react-redux = 4.4.1 redux-thunk = 0.5.3

當我運行它時,我沒有收到任何錯誤,但很明顯我的動作創建者正在解雇,但我的組件容器繼續而不是等待創建者完成。 就像我說的那樣,我確信我必須遺漏一些非常簡單的東西,但我似乎無法弄清楚那是什么。

先感謝您。 任何幫助將不勝感激。

  1. componentWillMount中的action(fetch)是異步的,組件不會等待。
  2. 通常,當您獲取某些數據時,您希望了解獲取過程的狀態。 喜歡“isfetching”以顯示加載器,成功和失敗以顯示錯誤。
  3. 您可以使用這些狀態來加載/裝載/啟動組件,直到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,
})

我不知道你的應用程序是什么樣的。 這個例子的目標是說明方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM