做者:Lusan Das翻譯:瘋狂的技術宅css
原文:https://blog.logrocket.com/th...html
未經容許嚴禁轉載前端
自從 React 團隊發佈他們的 16.x 願景以來,已經風靡了整個社區。它添加了一些很是酷的東西:Hooks、惰性加載、Suspense 和緩存 API。react
這不是又一篇關於如何編寫 Hook 的文章,而是對 React 將來的期待!若是你從沒有據說過 React Hooks 或其餘新的 API,那麼本文將會讓你對 React 的將來感到興奮。webpack
隨着文章的深刻,咱們將介紹兩個新概念,預計它們將會在 2019 年第二季度發佈:git
我已經很興奮了!可是在咱們進行深刻探討以前,先來快速回顧一下。程序員
在 React 16.8 中,Hooks 正式成爲穩定版本的一部分。它在高層次上解決了一些問題:github
componentDidMount
,componentDidUpdate
等,這會使咱們寫重複的代碼若是你想更詳細地瞭解這些,請查看此處。web
那麼,讓咱們看一下 React Hooks 的演示以及典型應用的外觀!面試
CodeSandbox上的演示:https://codesandbox.io/embed/...
<iframe style="width: 100%; height: 500px; border: 0; border-radius: 4px; overflow: hidden;" title="new" src="https://codesandbox.io/embed/...; sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"></iframe>
這個名字真的是暴露了它的意圖!當咱們想對組件進行惰性加載時會須要它:
const TodoList = React.lazy(() => import("./containers/todoList"));
在 webpack 動態導入的幫助下就能夠作到這些,它有助於建立 bundles ,從而提升頁面的加載速度。讓咱們作一個演示!回到前面 Codesandbox 的演示連接並將導入更改成如下內容:
const TodoList = React.lazy(() => import("./containers/todoList")); const CompletedList = React.lazy(() => import("./containers/completedList")); const AddNewTask = React.lazy(() => import("./containers/addNewTask"));
請注意下圖中獨立的 bundle 是如何建立的!😄
Suspense 用起來至關簡單。下面的代碼能夠幫你更好地理解這一點:
// https://codesandbox.io/s/new-6m2gj import React, { useState, useEffect, Suspense } from "react"; import ReactDOM from "react-dom"; import todoListData from "./containers/todoList/todolistData"; import Header from "./containers/header"; import Clock from "./components/Clock"; import "./styles.css"; const TodoList = React.lazy(() => import("./containers/todoList")); const CompletedList = React.lazy(() => import("./containers/completedList")); const AddNewTask = React.lazy(() => import("./containers/addNewTask")); function App() { const { todolist } = todoListData; const [todoListPayload, setTodoListPayload] = useState(todolist); const [completedTodoList, setCompletedTodoList] = useState([]); const addTodoTaskHandler = value => { // addTodoTaskHandler }; const removeTodoTaskHandler = ({ id }) => { // Remove from the set of todo list }; const completeTodoTaskHandler = ({ id }) => { // Get item to remove }; return ( <div className="App"> <Header title={"My Tasks"} /> <Clock /> <div className="PageLayout"> <Suspense fallback={<div>Loading...</div>}> <TodoList payload={todoListPayload} completeTodoTaskHandler={completeTodoTaskHandler} /> <CompletedList list={completedTodoList} /> <AddNewTask addTodoTaskHandler={addTodoTaskHandler} /> </Suspense> </div> </div> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);
若是你想運行它的話,能夠訪問這個演示連接。
若是咱們檢查演示中的代碼,就會看到:
<Suspense fallback={<div>Loading...</div>}> <TodoList payload={todoListPayload} completeTodoTaskHandler={completeTodoTaskHandler} /> <CompletedList list={completedTodoList} /> <AddNewTask addTodoTaskHandler={addTodoTaskHandler} /> </Suspense>
它就像用 Suspense 包裝組件同樣簡單。咱們用 React.lazy()
懶加載了一些組件: TodoList
, CompletedList
, AddNewTask
。因爲在內部它分別爲每一個組件生成 bundle,所以在網絡較慢的條件下,可能須要一些時間去加載它們。
Suspense 將經過顯示 fallback
(例如 Loading ...)或其餘任何組件(如 spinner 或相似組件)來自動處理。
前面的簡短回顧已經使人很是激動了。如今讓咱們爲 Suspense 帶來更多樂趣。
等等,咱們尚未講到 Suspense ?那麼若是我告訴你 Suspense 在調用 API 時也能夠處理咱們的加載狀態呢?不過在此以前咱們須要深刻研究並更好地理解它。
通過一番挖掘和研究,我終於找到了 Shawn Swyx Wang🌟 的 GitHub 存儲庫,我想直接引用他的文檔:
React Suspense 是組件在從緩存加載數據時暫停渲染的通用方法。它解決了當渲染是 I/O 綁定時的問題。
好的,「從緩存加載數據」給了我一個提示,但我須要更多關於如何真正處理API的信息。
Kent C. Dodds在他的 Egghead 課程中講授了一個重要概念:若是咱們拋出一個 promise,Suspense 就會自動知道已經調用了一個 API 請求。
import React, { Suspense } from "react"; fetchArticles() { // Some fetch API fetching articles } let isRequestCalled = false; function Content() { let result = []; if (!cache) { const promise = fetchArticles(); isRequestCalled = true; throw promise; // Let suspense know } return <div>Article</div>; } const Articles = () => { return ( <div> {/* Yay promise is thrown */} <Suspense fallback={<div>loading...</div>}> <Content /> </Suspense> </div> ); }; export default Articles;
固然,這不是處理代碼的最佳方式;它看起來有點麻煩。所以讓咱們試着用 react-cache 來更好地處理這些代碼:
import React, { Suspense } from "react"; import { unstable_createResource as createResource } from "react-cache"; function fetchArticles() { // Some fetch API fetching articles } const politicalArticles = createResource(fetchArticles); function Content() { const result = politicalArticles.read(someKey); return <div>Article</div>; } const Articles = () => { return ( <div> <Suspense fallback={<div>loading...</div>}> <Content /> </Suspense> </div> ); }; export default Articles;
來自 react-cache 的 createResource
從回調中建立資源,並返回一個 promise。
好吧,爲了讓 Suspense 知道它必須顯示加載狀態,所須要的只是一個 promise。在 promise 解決以前,它將繼續顯示加載狀態。
可是,這是實驗性的。我相信你會遇到錯誤,因此不要擔憂,很明顯 react-cache 仍處於開發階段。
一點要當心,確保在組件內部使用 read
方法,不然,它會拋出一個錯誤。
// A snippet from the React-cache library function readContext(Context, observedBits) { const dispatcher = ReactCurrentDispatcher.current; if (dispatcher === null) { throw new Error( 'react-cache: read and preload may only be called from within a ' + "component's render. They are not supported in event handlers or " + 'lifecycle methods.', ); } return dispatcher.readContext(Context, observedBits); }
若是你有興趣閱讀 react-cache 源代碼,請查看連接。
如今咱們抓住了 React 的不久的未來,有一件事是顯而易見的:React 團隊但願儘量的簡化 API。
我也對愈來愈多的庫正朝着函數式編程的方向發展而感到興奮。這種模式確定會完全改變咱們編寫前端的方式。我也在關注併發的 React —— 若是你有興趣,請查看官方的路線圖文檔。 React-cache 和 Suspense 是併發 react 的一部分功能😎。