Redux 思想

感想

近期一直在研究Redux,搞得一頭霧水,上週看了很多文檔,多數講的是數據之間的傳遞和使用方法,感覺機械搬copy相關代碼並無大用,萬一遇到什麼奇葩的項目,還是得另尋道路

上週搞了一直的redux,反覆架構實驗最後都沒有得到太多有用的東西,跟着教程一步一步來,卻沒有搞明白他的核心思想到底是什麼,一直到27號,找到了一些能夠引起我注意的東西,也許不是redux最核心的思想,但值得肯定的是,他在某些React Project with redux 中確實起到了關鍵的作用

上週的周志一直沒能好好寫,也是通過這篇日誌,算是給我的周志一個補充和安慰吧,問題還是在於redux到底是個什麼東西,很早就聽說redux是塊硬骨頭,如大家所說,確實難啃,而且目前看來,毫無味道,簡單的總結一下我是如何去啃這塊骨頭的


總結

你可能不需要 Redux

首先明確一點,Redux 是一個有用的架構,但不是非用不可。事實上,大多數情況,你可以不用它,只用 React 就夠了。

曾經有人說過這樣一句話。

“如果你不知道是否需要 Redux,那就是不需要它。”

Redux 的創造者 Dan Abramov 又補充了一句。

“只有遇到 React 實在解決不了的問題,你才需要 Redux 。”

簡單說,如果你的UI層非常簡單,沒有很多互動,Redux 就是不必要的,用了反而增加複雜性。

  • 用戶的使用方式非常簡單
    用戶之間沒有協作
  • 不需要與服務器大量交互,也沒有使用 WebSocket
    -視圖層(View)只從單一來源獲取數據

上面這些情況,都不需要使用 Redux。

  • 用戶的使用方式複雜
  • 不同身份的用戶有不同的使用方式(比如普通用戶和管理員)
  • 多個用戶之間可以協作
  • 與服務器大量交互,或者使用了WebSocket
  • View要從多個來源獲取數據

上面這些情況纔是 Redux 的適用場景:多交互、多數據源。

從組件角度看,如果你的應用有以下場景,可以考慮使用 Redux。

  • 某個組件的狀態,需要共享
  • 某個狀態需要在任何地方都可以拿到
  • 一個組件需要改變全局狀態
  • 一個組件需要改變另一個組件的狀態

發生上面情況時,如果不使用 Redux 或者其他狀態管理工具,不按照一定規律處理狀態的讀寫,代碼很快就會變成一團亂麻。你需要一種機制,可以在同一個地方查詢狀態、改變狀態、傳播狀態的變化。

總之,不要把 Redux 當作萬靈丹,如果你的應用沒那麼複雜,就沒必要用它。另一方面,Redux 只是 Web 架構的一種解決方案,也可以選擇其他方案。

Redux

設計思想

Redux 的設計思想很簡單,就兩句話。

(1)Web 應用是一個狀態機,視圖與狀態是一一對應的。

(2)所有的狀態,保存在一個對象裏面。

React-Redux

Redux 的作者封裝了一個 React 專用的庫 React-Redux,本文主要介紹它。

這個庫是可以選用的。實際項目中,你應該權衡一下,是直接使用 Redux,還是使用 React-Redux。後者雖然提供了便利,但是需要掌握額外的 API,並且要遵守它的組件拆分規範。

React&Redux

UI 組件

React-Redux 將所有組件分成兩大類:UI 組件(presentational component)和容器組件(container component)。

UI 組件有以下幾個特徵。

  • 只負責 UI 的呈現,不帶有任何業務邏輯
  • 沒有狀態(即不使用this.state這個變量)
  • 所有數據都由參數(this.props)提供
  • 不使用任何 Redux 的 API

下面就是一個 UI 組件的例子。

const Title =
  value => <h1>{value}</h1>;

因爲不含有狀態,UI 組件又稱爲"純組件",即它純函數一樣,純粹由參數決定它的值。

容器組件

容器組件的特徵恰恰相反。

  • 負責管理數據和業務邏輯,不負責 UI 的呈現
  • 帶有內部狀態
  • 使用 Redux 的 API

總之,只要記住一句話就可以了:UI 組件負責 UI 的呈現,容器組件負責管理數據和邏輯。

你可能會問,如果一個組件既有 UI 又有業務邏輯,那怎麼辦?回答是,將它拆分成下面的結構:外面是一個容器組件,裏面包了一個UI 組件。前者負責與外部的通信,將數據傳給後者,由後者渲染出視圖。

React-Redux 規定,所有的 UI 組件都由用戶提供,容器組件則是由 React-Redux 自動生成。也就是說,用戶負責視覺層,狀態管理則是全部交給它。

connect()

React-Redux 提供connect方法,用於從 UI 組件生成容器組件。connect的意思,就是將這兩種組件連起來。

import { connect } from 'react-redux'
const VisibleTodoList = connect()(TodoList);

上面代碼中,TodoList是 UI 組件,VisibleTodoList就是由 React-Redux 通過connect方法自動生成的容器組件。

但是,因爲沒有定義業務邏輯,上面這個容器組件毫無意義,只是 UI 組件的一個單純的包裝層。爲了定義業務邏輯,需要給出下面兩方面的信息。

(1)輸入邏輯:外部的數據(即state對象)如何轉換爲 UI 組件的參數

(2)輸出邏輯:用戶發出的動作如何變爲 Action 對象,從 UI 組件傳出去。

mapStateToProps()

mapStateToProps是一個函數。它的作用就是像它的名字那樣,建立一個從(外部的)state對象到(UI 組件的)props對象的映射關係。

作爲函數,mapStateToProps執行後應該返回一個對象,裏面的每一個鍵值對就是一個映射。

mapDispatchToProps()

mapDispatchToPropsconnect函數的第二個參數,用來建立 UI 組件的參數到store.dispatch方法的映射。也就是說,它定義了哪些用戶的操作應該當作 Action,傳給 Store。它可以是一個函數,也可以是一個對象。

如果mapDispatchToProps是一個函數,會得到dispatchownProps(容器組件的props對象)兩個參數。

組件

connect方法生成容器組件以後,需要讓容器組件拿到state對象,才能生成 UI 組件的參數。

一種解決方法是將state對象作爲參數,傳入容器組件。但是,這樣做比較麻煩,尤其是容器組件可能在很深的層級,一級級將state傳下去就很麻煩。

React-Redux 提供Provider組件,可以讓容器組件拿到state

import { Provider } from 'react-redux'
import { createStore } from 'redux'
import todoApp from './reducers'
import App from './components/App'

let store = createStore(todoApp);

render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)

參考文檔

文章來源:www.joynop.com/69.html

redux官方文檔-Read Me

Redux中文文檔

個人項目
ReactBlogwithRedux

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章