React + Redux 的一些建議(上篇)

Redux 並不是只和 React 結合使用的,它也可以和其他的很多類庫結合起來一起使用,即使你還未開始深入使用,你也可以閱讀文中的部分內容。

在深入 Redux 、Testing 或是其他更高級的使用之前,我們還是先開始 React 吧。

1、create-react-app:腳手架

我建議你可以首先採用 create-react-app 這個工具,他是Facebook For React 官方提供的零配置CLI 命令行工具。從技術上來說雖然它依然是一個腳手架,但是它屏蔽了所有的工具配置,你可以用它來快速生成一個React項目所需的基本工程。

sudo npm install create-react-app -g
create-react-app react-demo
cd react-demo && npm install
npm start

小結:
避免開始學習的時候就去使用腳手架
使用 create-react-app 去學習 react
當你熟悉 react之後
去探索工具本身如何使用
創建屬於你自己的項目腳手架

2、JSX 語法

ReactDOM.render
使用 setState 來改變組件的狀態 state
組件生命週期相關的方法
事件和表單
幾種創建組件的方式
複合組件 composeable
高階組件的使用和定義 HOC

3、什麼時候引入 Redux

在你遇到應用的狀態管理問題之前,你可以通過擴展應用的方式來解決,或是你在你的應用中壓根就沒遇到過這樣的問題,因爲你可以使用 setState 來很好的管理你的應用。但其實 setState 也不是那麼高效,畢竟它也不是萬能的。也許你會發現你已經在忙於處理太多的組件內部狀態,那麼,該是時候引入類似 Redux 等狀態管理庫了,不過有幾個事情需要注意:

在學習 Redux 前得先學好 React
可以閱讀以下You might not need Redux
不是所有的狀態都需要放在 Redux 的 Store 中,也不能完全取代 setState

4、聲明式的React組件

一般地,會有三種不同的方式來聲明一個組件:

React.createClass 使用這個API來定義組件
React ES6 class components 使用 ES6 的class 來定義組件
Functional stateless components 通過函數直接定義無狀態組件

// React.createClass
var TodoItem = React.createClass({ … })

// React ES6 class
class TodoItem extends React.Component { … }

// functional stateless component
function TodoItem() { … }

那什麼時候該用什麼方式來定義呢

無狀態組件:適合用來聲明沒有組件生命週期方法並且沒有內部狀態的組件。這種寫法很簡單,就是一個純函數,一個狀態輸入,輸出就是elements。

5、示意的僞代碼

(state) => View

這是一種最輕便最高效的組件聲明方式,這種組件沒有任何的內部狀態,使用的時候也無法訪問到組件的屬性,所以一般建議能用這種方式聲明組件的時候就儘量採用這種方式。

如果你需要使用組件生命週期方法,並且需要去處理組件內部狀態(this.state) ,或者需要獲取這個組件(this.ref)。那麼,這個時候建議你使用ES6的 class 來聲明組件。

另外,建議還是別用React.createClass這種方式聲明組件了,Facebook 官方在React V0.13版本的時候就說過,以後的目標是使用ES6 classes的方式來定義,會完全廢棄React.createClass

另外,這有兩篇博文也推薦給你看:

should-i-use-react-createclass-es6-classes-or-stateless-functional-components(http://jamesknelson.com/should-i-use-react-createclass-es6-classes-or-stateless-functional-components/
react-create-class-versus-component(https://toddmotto.com/react-create-class-versus-component/

輕量級的函數式無狀態組件

項目中一定需要去聲明很多組件,我們可以一起來完成一個 TodoList 組件:

function TodoList({ list }) {
return (


{map(list, (item) =>
{item.name}
)}

);
}

我們還可以按函數的方式將其拆分

function TodoList({ list }) {
return (


{map(list, (item) => )}

);
}

function TodoItem({ item }) {
return

{item.name}
;
}

這個例子有些簡單,無法很直接的看到這種定義方式的好處,但是當我們將組件拆分後將更具有可讀性、可複用性以及可維護性。這種方式很靈活,而且很輕鬆就可以聲明多個組件,一口氣不費勁,推薦使用。

簡潔的函數式無狀態組件

我們可以使用 ES6 的 arrow functions 讓組件的定義更加的清新。假如我們有一個這樣的組件:

function Button({ onClick, children }) {
return (

{children}

);
}

我們可以將其用 ES6 的語法改寫升級一下:

const Button = ({ onClick, children }) => {
return (

{children}

);
}

還可以再簡單嗎,我們來試一試:

const Button = ({ onClick, children }) =>

{children}

但這種方式就只允許我們的組件只有 props 作爲輸入,elements 作爲輸出。但如果我們希望在這中間做一些業務邏輯呢,我們可以將其再修改一下:

const Button = ({ onClick, children }) => {

// do something

return (

{children}

);
}

木偶組件Presenter Component和容器組件Container Component

好吧,這兩個詞聽起來實在是彆扭,聽我慢慢道來。

React 中的組件其實也只是應用狀態的一種表現方式,這讓我們可以非常清晰的通過 (State) => View 這樣的方式來理解。並且,組件內由處理程序來改變 state,從而改變不同 view 的展示。

那麼,木偶組件和容器組件有什麼區別或是怎麼理解呢。

木偶組件只接受傳遞進來的 props 和 callback,然後返回對應需要展示的 view,這種組件比較單純,大部分都是無狀態組件,給我啥我就展示啥,給我什麼callback我就執行callback,相同的輸入總能得到相同的輸出,像個機器人或是像個木偶,很純粹很簡單很可控;
而容器組件內更多的是關注邏輯,你需要在容器組件中準備好數據和一些callbac函數,在這裏處理一些事件或管理內部的狀態,給木偶組件傳遞所需的數據,大致的意思就是,容器組件對木偶組件說:調度或是邏輯處理的事就交給我吧,你需要啥我給你啥,你安心幹你的活就行,保證給我的產出即可。

當項目中使用了Redux的時候,Container Component 有個更好理解的名字,就是Connected Component。這類組件和Redux的store進行了連接,並且獲取到store的數據之後進行一些操作後傳遞給子組件。

Container components容器組件關注事情是怎麼做的,Presenter components木偶組件關注怎麼展現,各司其職,其樂融融。

另外,也再推薦給一篇文章smart-and-dumb-components,可以再更深入的理解。

什麼時候該用 Container Components 容器組件呢

前面聊完,我想你應該知道兩者的區別和使用場景了,但也許你還不太確定什麼時候該用什麼類型的組件。你可以定義一個Container Components,然後把一些Presenter Components都作爲他的子組件,這樣父組件關注如何工作,子組件關注如何展現。

但慢慢的,你發現父組件需要給子組件傳遞的properties和callbacks越來越多了,咋辦呢,現在是時候來介紹兩者如何結合使用了。

一般地,有個很好的原則:堅持presenter components不變,只新增一系列的container components去適應業務邏輯的改變。

把container component放到什麼地方呢

父組件container component只關注state如何處理,現在你可以評估一下你的preenter component下面的子組件了。也許你會注意到preenter component下面的子組件沒有被其他組件使用,那麼找到這個組件的父組件,給它添加一個用於管理狀態的container component,這樣,父級的container component就能夠變得更加清晰輕量,因爲它沒有必要去處理這些所有的狀態。
很多presenters component也許只是包含一些只是爲他們自己使用的props和callbacks,那麼,也給他們加上一個container component去處理這些邏輯,把這些邏輯放到container component,這樣將使父級的container component 再次變得輕量。

寫出你的第一個高階組件HOC吧

想象一下你需要展示一列內容,但是你不得不首先通過異步的方式獲取這些內容項。現在你需要一個加載指示器來顯示目前正在發送請求中,等請求完成後,你再展示獲取到的內容項。

不過你可以更進一步來學習HOC了,一個高階組件HOC將會返回一個增強的函數。

// 定義一個高階組件

function withLoadingSpinner(Component) {
return function EnhancedComponent({ isLoading, …props }) {
if (!isLoading) {
return

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