優雅的在React專案中使用Redux

Tybyq發表於2018-11-08

首先我們會用到哪些框架和工具呢?  React  UI框架  Redux  狀態管理工具,與React沒有任何關係,其他UI框架也可以使用Redux  react-redux  React外掛,作用:方便在React專案中使用Redux  react-thunk  中介軟體,作用:支援非同步action

|--src
    |-- store                Redux目錄
        |-- actions.js
        |-- index.js
        |-- reducers.js
        |-- state.js
    |-- components         元件目錄
        |-- Test.jsx
    |-- App.js               專案入口

準備工作  第1步:提供預設值,既然用Redux來管理資料,那麼資料就一定要有預設值,所以我們將state的預設值統一放置在state.js檔案:

// state.js// 宣告預設值// 這裡我們列舉兩個示例// 同步資料:pageTitle// 非同步資料:infoList(將來用非同步介面獲取)export default {    pageTitle: '首頁',    infoList: []
}

第2步:建立reducer,它就是將來真正要用到的資料,我們將其統一放置在reducers.js檔案

// reducers.js// 工具函式,用於組織多個reducer,並返回reducer集合import { combineReducers } from 'redux'// 預設值import defaultState from './state.js'// 一個reducer就是一個函式function pageTitle (state = defaultState.pageTitle, action) {  // 不同的action有不同的處理邏輯
  switch (action.type) {    case 'SET_PAGE_TITLE':      return action.data    default:      return state
  }
}function infoList (state = defaultState.infoList, action) {  switch (action.type) {    case 'SET_INFO_LIST':      return action.data    default:      return state
  }
}// 匯出所有reducerexport default combineReducers({
    pageTitle,
    infoList//歡迎加入全棧開發交流圈一起學習交流:864305860})//面向1-3年前端人員//幫助突破技術瓶頸,提升思維能力

第3步:建立action,現在我們已經建立了reducer,但是還沒有對應的action來操作它們,所以接下來就來編寫action

// actions.js// action也是函式export function setPageTitle (data) {  return (dispatch, getState) => {
    dispatch({ type: 'SET_PAGE_TITLE', data: data })
  }
}export function setInfoList (data) {  return (dispatch, getState) => {    // 使用fetch實現非同步請求
    window.fetch('/api/getInfoList', {        method: 'GET',        headers: {            'Content-Type': 'application/json'
        }
    }).then(res => {        return res.json()
    }).then(data => {        let { code, data } = data        if (code === 0) {
            dispatch({ type: 'SET_INFO_LIST', data: data })
        }
    })
  }
}

最後一步:建立store例項

// index.js// applyMiddleware: redux透過該函式來使用中介軟體// createStore: 用於建立store例項import { applyMiddleware, createStore } from 'redux'// 中介軟體,作用:如果不使用該中介軟體,當我們dispatch一個action時,需要給dispatch函式傳入action物件;但如果我們使用了這個中介軟體,那麼就可以傳入一個函式,這個函式接收兩個引數:dispatch和getState。這個dispatch可以在將來的非同步請求完成後使用,對於非同步action很有用import thunk from 'redux-thunk'// 引入reducerimport reducers from './reducers.js'// 建立store例項let store = createStore(
  reducers,
  applyMiddleware(thunk)
)export default store

至此,我們已經完成了所有使用Redux的準備工作,接下來就在React元件中使用Redux

開始使用  首先,我們來編寫應用的入口檔案APP.js

// App.jsimport React from 'react'import ReactDOM from 'react-dom'// 引入元件import TestComponent from './components/Test.jsx'// Provider是react-redux兩個核心工具之一,作用:將store傳遞到每個專案中的元件中// 第二個工具是connect,稍後會作介紹import { Provider } from 'react-redux'// 引入建立好的store例項import store from '@/store/index.js'// 渲染DOMReactDOM.render (
  (    <div>
        {/* 將store作為prop傳入,即可使應用中的所有元件使用store */}        <Provider store = {store}>
          <TestComponent />
        </Provider>
    </div>
  ),  document.getElementById('root')
)

最後是我們的元件:Test.jsx

// Test.jsximport React, { Component } from 'react'// connect方法的作用:將額外的props傳遞給元件,並返回新的元件,元件在該過程中不會受到影響import { connect } from 'react-redux'// 引入actionimport { setPageTitle, setInfoList } from '../store/actions.js'class Test extends Component {  constructor(props) {    super(props)
  }
  componentDidMount () {    let { setPageTitle, setInfoList } = this.props    
    // 觸發setPageTitle action
    setPageTitle('新的標題')    
    // 觸發setInfoList action
    setInfoList()
  }
  render () {    // 從props中解構store
    let { pageTitle, infoList } = this.props    
    // 使用store
    return (      <div>
        <h1>{pageTitle}</h1>
        {
            infoList.length > 0 ? (                <ul>
                    {
                        infoList.map((item, index) => {                            <li>{item.data}</li>
                        })
                    }                </ul>
            ):null
        }      </div>
    )
  }
}// mapStateToProps:將state對映到元件的props中const mapStateToProps = (state) => {  return {    pageTitle: state.pageTitle,    infoList: state.infoList
  }
}// mapDispatchToProps:將dispatch對映到元件的props中const mapDispatchToProps = (dispatch, ownProps) => {  return {
    setPageTitle (data) {        // 如果不懂這裡的邏輯可檢視前面對redux-thunk的介紹
        dispatch(setPageTitle(data))        // 執行setPageTitle會返回一個函式
        // 這正是redux-thunk的所用之處:非同步action
        // 上行程式碼相當於
        /*dispatch((dispatch, getState) => {
            dispatch({ type: 'SET_PAGE_TITLE', data: data })
        )*/
    },
    setInfoList (data) {
        dispatch(setInfoList(data))
    }
  }
}export default connect(mapStateToProps, mapDispatchToProps)(Test)


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31557424/viewspace-2219269/,如需轉載,請註明出處,否則將追究法律責任。

相關文章