[譯]在 React & Redux 中使用 AJAX 輪詢

更新: 查看最新關於使用 redux-saga 進行輪詢的文章:notjoshmiller.com/ajax-pollin…javascript

正如生活不老是給予你所需之物,你所用的 API 也不老是支持流式事件。所以,當你須要把一些有時序依賴的狀態從服務端同步到客戶端時,一個經常使用的 「曲線救國」 方法就是使用 AJAX 進行接口輪詢。咱們大部分人都知道使用 setInterval 並非處理輪詢的 「最佳人選」,不過它的堂兄 setTimeout 配合 遞歸解法 卻能夠大展身手。前端

React & Redux 爲咱們提供了響應式的數據流,咱們如何才能使普通的輪詢方法與其和諧共處?RxJS 以及其餘 Observable 類庫是處理輪詢的不錯選擇,不過除非你的項目已經集成了 Observable 類庫,不然僅爲解決輪詢而引入相關類庫顯得並不值當。當前經過結合 React 組件的生命週期方法和 Redux 的 Action 就已經足夠處理 AJAX 輪詢,下面來看看如何得解?java

首先經過 Redux 的 Reducer 來講明當前 State:react

const initialState = {  
    data: {},
    isFetching: false
};

export function data (state = initialState, action) {  
    switch (action.type) {
    case DATA_FETCH_BEGIN: {
        return { ...state, isFetching: true };
    }
    case DATA_FETCH_SUCCESS: {
        return { isFetching: false, data: { ...state.data, action.payload }};
    }
    case DATA_FETCH_ERROR: {
        return { ...state, isFetching: false };
    }
    default:
        return state;
}
複製代碼

我不會在這裏去講解如何處理 Redux 中的異步 Action 建立函數,想更好地瞭解這方面知識請參考 Redux 文檔中的異步示例。 如今只需假設咱們已有相關的 Redux 中間件來處理本文提到的各類 Action 。我會使用與 real-world example(譯註:原文連接的倉庫已不存在,能夠參考 Redux 文檔中同名例子)中類似形式的 Action 建立函數。jquery

對應上方的數據模型,咱們的 Action 建立函數可能爲:android

export function dataFetch() {  
  return {
    [CALL_API]: {
      types: [DATA_FETCH_BEGIN, DATA_FETCH_SUCCESS, DATA_FETCH_ERROR],
      endpoint: 'api/data/'
    }
  };
}
複製代碼

回到最初的問題,讓咱們想一想你會如何實現 API 接口的輪詢。你會把輪詢的定時器設置在 Reducer 中?仍是 Action 建立函數裏?或許是中間件裏?若是把定時器放到 Smart 組件(譯註:參看 Smart and Dumb Components - Medium)中怎麼樣呢?我會選擇在組件中設置定時器,不只是由於組件須要控制自身的數據依賴,並且咱們能夠經過組件的生命週期方法控制這些定時器,看看如何作到?ios

import React from 'react';  
import {connect} from 'react-redux';  
import {bindActionCreators} from 'redux';  
import * as DataActions from 'actions/DataActions';

// 組件須要哪些 Redux 全局狀態做爲 props 傳入?
function mapStateToProps(state) {  
    return {
        data: state.data.data,
        isFetching: state.data.isFetching
    };
}

// 組件須要哪些 Action 建立函數做爲 props 傳入?
function mapDispatchToProps(dispatch) {  
    return {
        dataActions: bindActionCreators(DataActions, dispatch)
    };
}

@connect(mapStateToProps, mapDispatchToProps)
export default class AppContainer {  
    componentWillReceiveProps(nextProps) {
        if (this.props.data !== nextProps.data) {

            clearTimeout(this.timeout);

            // 你能夠在這裏處理獲取到的數據

            if (!nextProps.isFetching) {
                this.startPoll();
            }
        }

    }

    componentWillMount() {
        this.props.dataActions.dataFetch();
    }

    componentWillUnmount() {
        clearTimeout(this.timeout);
    }

    startPoll() {
        this.timeout = setTimeout(() => this.props.dataActions.dataFetch(), 15000);
    }
}
複製代碼

好了,大功告成。由於上面的組件須要一些額外數據進行渲染,因此它會在掛載的時候嘗試獲取這些數據。 當 dataFetch 發送了一個新 Action 後,咱們的 Reducer 會返回新的狀態, 進而觸發組件的 componentWillReceiveProps 方法。在這個生命週期方法內會首先清除全部進行中的定時器,若當前沒有進行數據請求則隨即啓動一個新定時器。git

誠然還有不少方法能夠處理這裏的接口輪詢問題,而且若是有任何長輪詢方法可用時,此處的輪詢方法便相形見絀。不過我仍是但願這篇文章能夠幫助闡明結合 React 生命週期方法和 Redux 數據流的處 「事」 之道。github


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄ajax

相關文章
相關標籤/搜索