A graphic with the words “Loaders” -> “Component” -> “Action” connected by arrows and depicted cyclically.
2022 年 6 月 22 日

Remix 中的資料流

Jim Nielsen
設計總監

當 React 初次問世時,它最引人注目的特性之一就是其「單向資料流」。這仍然在 React 文件中的「以 React 思考」頁面中概述。

階層結構頂端的元件會將您的資料模型作為 prop 接收。如果您變更底層資料模型並再次呼叫 root.render(),UI 將會更新。您可以查看 UI 如何更新以及在哪裡進行變更。React 的單向資料流(也稱為單向綁定)可讓一切保持模組化且快速。

其概念是資料只能在您的應用程式中單向流動,因此使您的應用程式更易於直觀理解和推理。

Illustration of the idea of one-way data flow depicting lines drawing a circular flow from view to action to state.

這最終被總結為短語:「UI 是狀態的函數」,或 ui = fn(state)。每當某些狀態因動作而改變時,視圖就會重新渲染。迄今為止,已經創建了許多複雜的「狀態管理」解決方案,以促進使用此心智模型構建應用程式。

然而,這裡很少被承認的問題是,這種「單向資料流」有點用詞不當。它實際上是在客戶端的單向資料流。但是僅在客戶端擁有資料很少實用。大多數時候,您需要持久保存資料,也就是同步資料,這表示您需要資料雙向流動:在客戶端和伺服器之間。

Illustration of the flow “View -> Action -> State” framed in a browser on the left. On the right is an illustartion of a server with a database. Two arrows connect these two illustrations denoting network transfer.

許多狀態管理工具僅幫助您管理客戶端上的狀態,但它們無法幫助您有效地跨越網路鴻溝:客戶端上的狀態與伺服器上的狀態之間的差距。

Illustration of the flow “View -> Action -> State” framed in a browser on the left. On the right is an illustartion of a server with a database. Two arrows connect these two illustrations denoting network transfer. The visual emphasis is on the network part of the graphic with “?”s surrounding it.

進入 Remix:「Remix 的主要功能之一是簡化與伺服器的互動,以將資料載入元件。」Remix 將資料流擴展到整個網路,使其真正成為單向且循環的:從伺服器(狀態)到客戶端(視圖),然後回到伺服器(動作)。

Illustration of the flow “View -> Action -> State” crossing between the browser and the server.

當說您的「UI 是狀態的函數」時,更細緻地闡明該陳述中的假設的方式是:UI 是您的遠端狀態您的本地狀態的函數。在傳統的 React 應用程式中,所有狀態都存在於客戶端,而您要持久保存的部分必須跳出「單向資料流」並跨網路同步到伺服器。您可以想像,這是一個容易出錯的區域。

然而,在 Remix 中,「UI 作為狀態的函數」的概念得到了轉變,因為遠端狀態可以更容易地與本地狀態分離。「有什麼區別?」您會問。這樣想。

遠端狀態是任何需要持久保存的資料,例如使用者資料。此狀態(例如,使用者有多少未讀通知?)會儲存在客戶端之外,並透過 Remix 機制(例如 loadersactions)協調到您的應用程式中。

注意:Remix 還透過 transitionsfetchers 提供有關持久資料傳輸的狀態資訊,從而協助您跨越網路鴻溝。您無需透過布林值(例如 isLoading)或列舉(例如 initial | loading | success | failed)自行追蹤每個網路請求的狀態)。

相反地,本地狀態是暫時的資料,可以在不對使用者體驗產生負面影響的情況下遺失(例如,透過重新整理)。此狀態(例如,下拉式選單是否已開啟,以顯示使用者的通知?)會透過 React 狀態或本機儲存等機制儲存在客戶端上。重要的是,它不需要持久保存並跨網路同步,從而降低了複雜性和產生錯誤的可能性。

Illustration depicting a one-way flow of “remote data” between the client/server facilitated by remix. A one-way flow of “local data” is on the client exclusively facilitated by React and/or localStorage.

表單、fetchers、loaders、actions,這些都是 Remix 中的「狀態管理」解決方案(儘管我們不這樣稱呼它們)。它們為您提供了保持客戶端和伺服器之間持久狀態同步的工具,確保資料在您的應用程式中以及跨網路單向循環流動:從 loaders 到元件,再到 action,然後再返回。

The words “Loader” -> “Action” -> “Component” shown in a circular diagram.

使用 Remix,您的 UI 會成為跨網路的狀態函數,而不僅僅是在本機。Remix 的資料抽象與 React 的虛擬 DOM 抽象有一個 有趣的類比

在 React 中,您無需擔心自己更新 DOM。您設定狀態,虛擬 DOM 會執行所有差異比較,以找出如何對 DOM 進行有效率的更新。Remix 將這個概念擴展到持久資料的 API 層。

在 Remix 中,您無需擔心保持客戶端狀態與伺服器同步。您透過變更來「設定狀態」,並且 loaders 會接管以重新擷取最新的資料並更新您的元件視圖。

Screenshot of code example in Remix illustrating the one-way, cyclical flow of data through an app. There’s a loader function whose code flows into the Route component whose code, via a <Form> flows into the action function whose code flows back into a loader again.

希望這有助於說明 Remix 如何大幅減少建置更好的網站所需的複雜程度。正如 Kent 在他在 RenderATL 的演講中所說,由於 Remix 在 JavaScript 之前就開始運作,這對您的使用者來說是一項勝利,因為他們獲得了漸進式增強所支援的體驗。但這對您作為開發人員來說也是一項勝利,因為您不需要建構傳統上與狀態管理解決方案相關的所有複雜性。

當您使用 Remix 時,您不必擔心應用程式狀態管理。Redux、Apollo,儘管這些工具很酷,但當您使用 Remix 時,您不需要它們,因為我們甚至不需要客戶端 JavaScript 就可以讓整個應用程式運作…[想想您正在建置的應用程式],並假設您可以丟棄所有與應用程式狀態管理相關的程式碼…這就像您使用 Remix 時一樣。如果它可以不使用瀏覽器中的 JavaScript 運作,那就表示您在瀏覽器中不需要任何需要狀態管理的東西。


取得有關最新 Remix 新聞的更新

成為第一個了解新 Remix 功能、社群活動和教學課程的人。