標籤:

翻譯 | React AJAX最佳實踐

作者:Oral (滬江Web前端開發工程師)

本文原創翻譯,有不當的地方歡迎指出。轉載請指明出處。

當你問起有關AJAX與React時,老司機們首先就會告訴你:React其實是個沒有網路請求/AJAX功能的view庫。這種說法很容易理解,但對於當你僅想讓你的React組件從伺服器上獲取數據時,是沒啥幫助的。

事實上,有很多種方法可以滿足你的需求。也許你自己也腦洞大開考慮過幾個,但一旦走錯了方向,那代碼可就一團糟了。

好吧,這下你好奇了:到底什麼才是正確的、值得首選的方法呢?

答案是……看情況~~~

下面為大家一一介紹我收集的在React里使用AJAX的四個好方法。不過要注意的是,得根據app的大小及複雜度,和你已使用的庫和技術來決定該使用哪種方法。

1. 根組件(Root Component)方法

這是一種最簡單的方法,因此它適用於簡單或小型的應用。

通過這種方法,你可以建立單一根組件(父層組件)去分發所有AJAX請求,然後它會把AJAX響應數據存儲進state里,以props方式傳遞到子組件。可以參考下官方教程上的實例。

官方教程上的實例

facebook.github.io/reac

此實例中的CommentBox組件就是個分發所有AJAX請求的根組件。

不過,我不大喜歡官方教程實例中的一點:它使用了jQuery去發送AJAX請求。

jQuery是個有很多功能的大庫,因此僅因AJAX而引入它是沒多大意義的。

我推薦使用fetch()這個簡單、標準化的JavaScript 網路請求API,它已被Chrome、Firefox瀏覽器支持,並且可以通過使用fetch polyfill去兼容其他瀏覽器。如果想要更具體地了解,大家可以參考我的《AJAX庫之對比》,也許這對你選擇自己的AJAX庫有點幫助。

AJAX庫之對比

andrewhfarmer.com/ajax-

注意:如果你的項目有著很深的組件樹結構(子組件層層嵌套下去),那麼就會需要把數據從根組件一層一層傳遞至子組件,而這個傳遞數據之路將比較長。

適宜使用root component 方法的場景:

1、項目組件樹比較簡單

2、項目中沒有使用Redux或flux

2. 容器組件方法(Container Components)

容器組件就是「為展示組件或其它容器組件提供數據和方法的組件」,如果你還沒有聽過這個概念,建議你可以先閱讀下Dan Abramov的有關展示組件和容器組件的文章。

展示組件和容器組件

medium.com/@dan_abramov

容器組件方法與根組件方法很像,不同的是容器組件可以支持多組件與伺服器端交互。(根組件方法僅支持通過單一組件與伺服器端交互)

容器組件方法是這樣工作的:對於每個需要從伺服器拿到數據的展示組件來說,需要有個可以發送網路請求的容器組件來把請求到的數據通過props傳遞給子組件。

舉個具體的栗子:你想要展示一個有著name和picture的用戶簡介。我們該怎麼去做呢?接下來,我們一步步來:

1.建立一個展示組件:<UserProfile />, 這個組件可以接收到name 和profileImage 數據。但是這個組件一定不能有任何AJAX請求代碼。 2.建立組件<UserProfileContainer /> ,這個組件用來接收urserId .它請求到用戶的數據以後通過props傳遞給剛才創建的組件<UserProfile />。

這樣用戶簡介展示就實現了。容器組件中的AJAX請求將會由簡單的AJAX庫發送出去,這裡我推薦使用fetch()方法。

fetch()方法

andrewhfarmer.com/ajax-

適宜為網路請求使用容器組件方法的場景:

1.項目組件樹比較深n2.項目中除了某些組件需要從伺服器上獲取數據,絕大多數組件是不需要的。n3.項目需要從多端或多個API中獲取數據。n4.項目中沒有使用Redux或flux. 或者與』非同步操作』方法相比,你更喜歡使用容器組件方法來完成請求數據功能。n

3.Redux Async Actions

Redux管理數據,而AJAX提供伺服器上的數據,因此Redux 應用於處理網路請求。

如果使用Redux,就不要把AJAX放進React組件裡面,而是要放進Async Actions里。

Async Actions

redux.js.org/docs/advan

這裡我還是推薦fetch()方法去處理實際網路請求,幸運地,Redux官方文檔上也是使用fetch().文檔中已有一個使用Redux、React和fetch()方法的實例

example reddit API.

redux.js.org/docs/advan

如果你使用flux,那這個方法也是類似的——在actions中發送網路請求。

適宜使用Redux Async Actions的場景:

1.項目中正使用著Reduxn2.項目中正使用著flux,使用方式也是類似的n

4. Relay

通過Relay,你需要使用GraphQL聲明React組件需要的數據,然後,Relay會自動下載數據並傳遞至組件的props中。

Relay

facebook.github.io/rela

Relay很適用於一個大型應用中,但是對於使用者來說,還是需要比較豐富的前期知識儲備的。你需要:

1.學習Relay和GraphQL.n2.使用GraphQL指定React組件的數據需求,而不是使用propTypes來指定n3.準備一台GraphQL伺服器n

Relay僅意味著要連接GraphQL伺服器,因此它不會幫你連接任何第三方API.

目前,Relay僅能連接單一GraphQL伺服器,因此,如果你要從多台伺服器中獲取數據,那Relay方法就不適用了。不過,將來有可能支持連接多台伺服器,這個問題已經在github上討論得熱火朝天了。

github上討論

github.com/facebook/rel

如果你要繼續研究Relay方法,那Realy Playground 是個搞清楚它如何工作的好地方。

Realy Playground

facebook.github.io/rela

適宜使用Relay方法的場景:

1.想要創建一個大型應用而又比較關心Relay設計去解決的問題(https://facebook.github.io/react/blog/2015/05/01/graphql-introduction.html#why-invent-something-new)n2.項目中還沒有建立JSON APIn3.為項目準備一台GraphQL伺服器n4.項目只會連接單一伺服器n

彩蛋:反模式

如果以上方法都是正確的,那麼什麼方法是錯誤的呢?下面我來介紹兩種大家盡量要避免使用的方法。

反模式 1:在展示組件中使用AJAX請求

已經用作負責其他功能(如複雜界面渲染)的組件中就不要添加AJAX邏輯了,否則只會違反關注點分離的設計原則。

關注點分離

en.wikipedia.org/wiki/S

反模式2:ReactDOM.render()

你可以使用完全遊離於React之外的AJAX邏輯,當數據無論何時更新時,調用ReactDOM.render()來更新頁面。

ReactDOM.render()

facebook.github.io/reac

這個方法也許可以正常運行。將它以反模式方式提出來,是因為我堅信第一種根組件方法雖與其類似,但簡潔多了。

結論:

使用React建立的應用都是模塊化的,React會成為其中一個模塊,AJAX庫是另一個模塊。而使用Rails和Angular框架的應用,Rails或Angular則不會成為應用中的模塊。

原文:andrewhfarmer.com/react

iKcamp原創新書《移動Web前端高效開發實戰》已在亞馬遜、京東、噹噹開售

推薦閱讀:

知乎網站的性能都有些什麼瓶頸?可以以何種技術和方式解決?
怎樣合理地使用 Ajax ?過度使用 Ajax 會有哪些弊端?
115登錄頁的long polling在chrome裡面為什麼看不到返回結果?
怎樣防止重複發送 Ajax 請求?
如今的網站是否可以設計成只有一個html(內容框架),全站無跳轉?

TAG:React | Ajax |