- 原文地址:AJAX POLLING IN REACT WITH REDUX
- 原文做者:Josh M
- 譯文出自:掘金翻譯計劃
- 本文永久連接:github.com/xitu/gold-m…
- 譯者:劉嘉一
- 校對者:yoyoyohamapi,FateZeros
更新: 查看最新關於使用 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
掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。ajax