Redux使用教程
首先建立一個React元件components/ItemList.js用來抓取和顯示條目列表。設定這個靜態元件帶有狀態包含各種items輸出,2個boolean狀態表示在抓取載入時正常和出錯的結果。
import React, { Component } from 'react'; class ItemList extends Component { constructor() { super(); this.state = { items: [ { id: 1, label: 'List item 1' }, { id: 2, label: 'List item 2' }, { id: 3, label: 'List item 3' }, { id: 4, label: 'List item 4' } ], hasErrored: false, isLoading: false }; } render() { if (this.state.hasErrored) { return <p>Sorry! There was an error loading the items</p>; } if (this.state.isLoading) { return <p>Loading…</p>; } return ( <ul> {this.state.items.map((item) => ( <li key={item.id}> {item.label} </li> ))} </ul> ); } } export default ItemList; <p class="indent"> |
當渲染時,這個元件應該輸出4個條目列表,但是如果設定 isLoading或hasErrored為true時,也會有相應狀態輸出。
假設我們從 JSON API抓取items,使用Fetch API實現非同步請求,它比傳統的XMLHttpRequest更方便,能夠返回一個響應的promise,Fetch並不適合所有瀏覽器,需要加入你專案依賴:
npm install whatwg-fetch --save
抓取邏輯很簡單:
1.首先,設定初始化items為空陣列[]
2.加入抓取方法,設定loading和錯誤資訊
fetchData(url) { this.setState({ isLoading: true }); fetch(url) .then((response) => { if (!response.ok) { throw Error(response.statusText); } this.setState({ isLoading: false }); return response; }) .then((response) => response.json()) .then((items) => this.setState({ items })) // ES6 property value shorthand for { items: items } .catch(() => this.setState({ hasErrored: true })); } <p class="indent"> |
這樣,當元件安裝時我們可以呼叫它:
componentDidMount() { this.fetchData('http://5826ed963900d612000138bd.mockapi.io/items'); } <p class="indent"> |
這樣,整個元件程式碼:
class ItemList extends Component { constructor() { this.state = { items: [], }; } fetchData(url) { this.setState({ isLoading: true }); fetch(url) .then((response) => { if (!response.ok) { throw Error(response.statusText); } this.setState({ isLoading: false }); return response; }) .then((response) => response.json()) .then((items) => this.setState({ items })) .catch(() => this.setState({ hasErrored: true })); } componentDidMount() { this.fetchData('http://5826ed963900d612000138bd.mockapi.io/items'); } render() { } } <p class="indent"> |
現在,我們已經有一個沒有使用redux普通的抓取元件,從一個REST端點抓取條目列表,在條目全部抓取出現之前,顯示loading。。狀態,而如果發生錯誤,可以顯示錯誤。
無論如何,一個元件不應該包含抓取資料的邏輯,資料也不應該儲存在元件的狀態中,要解決這兩個問題,就需要redux。
下面我們將上面案例程式碼轉換為redux,我們需要加入Redux,為了在Redux中實現非同步呼叫,我們還需要Redux Thunk。
什麼是Thunk?Thunk是一個函式,用於包裝一個表示式以延遲其計算結果的獲得,看下面程式碼:
// 立即計算 1 + 2 // x === 3 let x = 1 + 2; // 1 + 2計算被延遲 // foo 能在以後被呼叫時再進行計算 // foo 就是一個 thunk! let foo = () => 1 + 2; <p class="indent"> |
下面是在我們當前案例安裝Redux, React Redux和Redux Thunk:
npm install redux react-redux redux-thunk --save
理解Redux
Redux有一些核心原理我們需要理解:
1.有一個全域性狀態物件管理整個應用的狀態,在這個案例中,它是類似於我們這個最初元件的狀態,這屬於真相單一來源。
2.只有一個辦法才能修改狀態,只能透過一個動作action,這是一個用來表示改變操作的物件,Action Creators是專門用來派發每個改變的函式,所做的就是返回一個動作action物件。
3.當一個動作action被派發時,一個Reducer函式將實際改變這個動作所要改變的狀態,如果動作不適合這個Reducer,就返回已經存在狀態。
4.Reducer時純函式,它們不會有副作用,沒有可變狀態,它們都必須返回一個修改的複製,
5.獨立reducer被結合到單個rootReducer上,以建立狀態的各種離散狀態。
6.Store是將上面所有東西都結合一起,透過使用rootReducer代表狀態,允許你真正dispatch動作action
7.對於在React中使用Redux,<Provider />元件包裝整個應用,傳遞store下傳到所有子成員。
設計狀態
從開始工作到現在,我們已經明白我們狀態需要有三個屬性: items,hasErrored,isLoading,對應三個動作action。
但是Action Creators不同於動作action,不需要與狀態有1:1關係,我們需要第四個action creator來呼叫其他三個action creators,這取決於抓取資料的狀態,這第四個action creator幾乎等同於我們這個案例原始fetchData()方法,但是不是使用this.setState({ isLoading: true }) 方法來直接修改狀態,我們透過派發dispatch一個動作action來做同樣事情:dispatch(isLoading(true))
建立動作action
讓我們建立actions/items.js檔案來放我們的action creators,我們首先開始3個簡單動作:
export function itemsHasErrored(bool) { return { type: 'ITEMS_HAS_ERRORED', hasErrored: bool }; } export function itemsIsLoading(bool) { return { type: 'ITEMS_IS_LOADING', isLoading: bool }; } export function itemsFetchDataSuccess(items) { return { type: 'ITEMS_FETCH_DATA_SUCCESS', items }; } <p class="indent"> |
正如之前提到,action creators會返回一個動作action,我們使用export以便以後在其它程式碼地方使用它們。
第二個action create獲取bool(true/false)作為引數,返回帶有意義的一個type和一個分配有具體相應屬性的bool這兩個型別的物件。
第三個itemsFetchSuccess是當資料被成功抓取時呼叫,將資料作為items傳遞,透過ES6的value shorthands魔術,我們返回一個物件,帶有屬性items,它的值將是items的陣列。
現在我們有3個動作action代表我們的狀態,我們將轉換原來元件的fetchData方法為itemsFetchData()這樣新的action creator。
預設情況下,Redux的action creators不會支援非同步動作,比如非同步抓取資料,這裡就需要使用Redux Thunk,它能讓你編寫action creator返回一個函式而不是一個動作action物件,內部函式能夠接受store方法dispatch和getState作為引數,但是我們只使用dispatch。
如果不使用thunk,實現非同步的最簡單方法是5秒後手工觸發itemsHasErrored方法:
export function errorAfterFiveSeconds() { // We return a function instead of an action object return (dispatch) => { setTimeout(() => { // This function is able to dispatch other action creators dispatch(itemsHasErrored(true)); }, 5000); }; } <p class="indent"> |
現在有了Thunk,我們編寫itemsFetchData方法:
export function itemsFetchData(url) { return (dispatch) => { dispatch(itemsIsLoading(true)); fetch(url) .then((response) => { if (!response.ok) { throw Error(response.statusText); } dispatch(itemsIsLoading(false)); return response; }) .then((response) => response.json()) .then((items) => dispatch(itemsFetchDataSuccess(items))) .catch(() => dispatch(itemsHasErrored(true))); }; } <p class="indent"> |
待續。。。
A Dummy’s Guide to Redux and Thunk in React – Medi
[該貼被tecentID39C3D於2016-11-18 13:16修改過]
相關文章
- Redux 概要教程Redux
- Redux入門教程Redux
- Redux 基礎教程以及結合 React 使用方式ReduxReact
- Redux-saga框架使用詳解及Demo教程Redux框架
- Redux 入門教程(3):React-Redux 的用法ReduxReact
- Redux 入門教程(三):React-Redux 的用法ReduxReact
- [譯】Redux入門教程(二)Redux
- Redux開發實用教程Redux
- Redux教程2:連結ReactReduxReact
- Redux 入門教程(1):基本用法Redux
- Redux 入門教程(一):基本用法Redux
- 使用Hook寫ReduxHookRedux
- redux簡單使用Redux
- Redux 莞式教程 之 簡明篇Redux
- Redux教程3:新增倒數計時Redux
- Redux入門到使用Redux
- Fish Redux 使用指南Redux
- react之redux的使用ReactRedux
- react-redux 的使用ReactRedux
- 在 React 中使用 ReduxReactRedux
- React - React 中使用 ReduxReactRedux
- React-Redux進階(像VUEX一樣使用Redux)ReactReduxVue
- Redux中介軟體之redux-thunk使用詳解Redux
- redux-observable 使用小記Redux
- React中理解並使用ReduxReactRedux
- redux和mobx入門使用Redux
- Rims - 換個方式使用 ReduxRedux
- React-Redux簡單使用ReactRedux
- redux在react-native上使用(三)–加入redux-thunkReduxReact
- redux在react-native上使用(三)--加入redux-thunkReduxReact
- React Native+Redux開發實用教程React NativeRedux
- 在Flutter中封裝redux的使用Flutter封裝Redux
- 在微信小程式中使用redux微信小程式Redux
- 讓Vue也可以使用ReduxVueRedux
- react學習系列5使用reduxReactRedux
- Redux在React中的使用小結ReduxReact
- 使用 Typescript 踩 react-redux 的坑TypeScriptReactRedux
- 初識Fish Redux在Flutter中使用ReduxFlutter