做者:Lusan Dascss
翻譯:瘋狂的技術宅html
原文:blog.logrocket.com/the-future-…前端
未經容許嚴禁轉載react
自從 React 團隊發佈他們的 16.x 願景以來,已經風靡了整個社區。它添加了一些很是酷的東西:Hooks、惰性加載、Suspense 和緩存 API。webpack
這不是又一篇關於如何編寫 Hook 的文章,而是對 React 將來的期待!若是你從沒有據說過 React Hooks 或其餘新的 API,那麼本文將會讓你對 React 的將來感到興奮。git
隨着文章的深刻,咱們將介紹兩個新概念,預計它們將會在 2019 年第二季度發佈:github
我已經很興奮了!可是在咱們進行深刻探討以前,先來快速回顧一下。web
在 React 16.8 中,Hooks 正式成爲穩定版本的一部分。它在高層次上解決了一些問題:編程
componentDidMount
,componentDidUpdate
等,這會使咱們寫重複的代碼若是你想更詳細地瞭解這些,請查看此處。前端工程化
那麼,讓咱們看一下 React Hooks 的演示以及典型應用的外觀!
CodeSandbox上的演示:codesandbox.io/embed/3rm5j…
這個名字真的是暴露了它的意圖!當咱們想對組件進行惰性加載時會須要它:
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 是如何建立的!😄
使用 Webpack 建立的BundleSuspense 用起來至關簡單。下面的代碼能夠幫你更好地理解這一點:
// 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 的一部分功能😎。