国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Hooks + Context:狀態管理的新選擇

tommego / 3309人閱讀

摘要:用戶點擊改變全局狀態崔然渲染整顆組件樹有沒有解決方案呢當然有創建一個只接收的新組件,并將組件中的邏輯都移到組件中。最終的示例使用全局狀態和生成全局狀態和崔然完整示例見結論在和出現之前,缺乏自帶的全局狀態管理能力。

React 16.3 版本,正式推了出官方推薦的 context API —— 一種跨層級的數據傳遞方法。React 16.8 版本,推出了全新的 hooks 功能,將原本只有 class 組件才有的狀態管理功能和生命周期函數功能,賦予了 function 組件。Hooks 配合 context 一起使用,為 react 狀態管理提供了一種新的選擇。這可能會減少開發者對 redux 等狀態管理庫的依賴。

本文首先會對官方的 context 作簡單介紹,并搭建一個十分簡單的使用全局狀態的應用。然后再對 hooks 的基本 API useState useEffect 做基本介紹。接著使用 useContext hooks 對應用進行重構,讓 context 的使用變得更優雅。再使用 useReducer hooks 來管理多個狀態。最后,待充分理解 hooks 和 context 之后,我們將它們搭配起來用,對整個應用進行狀態管理。

Context 概述

React 中存在一個眾所周知的難題,那就是如何管理全局狀態。即便是最基礎的全局狀態跨越層級傳遞,也是非常麻煩。此時,首選的解決方案就是使用狀態管理庫,如 redux。Redux 本身是一個 API 非常少的狀態管理工具,其底層也是用 context 實現的。在一些狀態管理不是那么復雜,但是又有跨越層級傳遞數據的需求時,不妨考慮使用 context 直接實現。

例如,一個 Page 組件包含全局狀態 user ,需要經過多次props的傳遞,層級很深的 Avatar 組件才能使用它。


// ... render ...

// ... render ...

// ... render ...
Context :跨層級傳遞數據

Context 提供了一種方法,解決了全局數據傳遞的問題,使得組件之間不用顯式地通過 props 傳遞數據。

React.createContext: 創建一個 Context 對象,該對象擁有 Provider 和 Consumer 屬性。

Context.Provider: 接受一個 value 參數,在 value 參數更新的時候通知 Consumer。

Context.Consumer: 訂閱 value 參數的改變。一旦 value 參數改變,就會觸發它的回調函數。

使用 context 重構的之后,跨層級傳遞數據就變得容易很多:

// 創建一個 context
const UserContext = React.createContext();

class App extends React.Component {
 state = { user: "崔然" };

 setUser = user => {
   this.setState({ user });
};

 render() {
   // 設置 context 當前值為 {user, setUser}
   return (
     
       
     
  );
}
}

// ... Page render ...

// ... PageLayout render ...

// ... NavigationBar render ...
// 無論組件有多深,都可以**直接**讀取 user 值

{ ({user, setUser}) =>  }
避免全局渲染

但是,在使用 context 時,有些寫代碼的小技巧,需要特別注意。不然在全局狀態改變時, Provider 的所有后代組件都會重新渲染。例如,用戶點擊 Avatar 組件后,將 崔然 更新為 CuiRan,這時會調用根組件的 setUser 方法。根組件 setState({ user }) 更新狀態,會導致整顆組件樹重新渲染。

const Avatar = ({ user, setUser }) => {
 // 用戶點擊改變全局狀態
 return 
setUser("CuiRan")}>{user}
; }; class App extends React.Component { state = { user: "崔然" }; setUser = user => { this.setState({ user }); }; // ... 渲染整顆組件樹 }

有沒有解決方案呢?當然有!

創建一個只接收 props.children的新組件 AppProvider ,并將 App 組件中的邏輯都移到 AppProvider組件中。通過備注的 console 日志可以看到,該方式避免了不必要的渲染。

const Avatar = ({ user, setUser }) => {
 // 用戶點擊改變全局狀態
 return 
setUser("CuiRan")}>{user}
; }; // 將 App 邏輯移到 AppProvider const UserContext = React.createContext(); class AppProvider extends React.Component { state = { user: "崔然" }; setUser = user => { this.setState({ user }); }; render() { return ( {this.props.children} ); } } // APP 只保留根組件最基本的 JSX 嵌套 const App = () => ( ); // ... Page not render ... // ... PageLayout not render ... // ... NavigationBar not render ... // Consumer 監聽到 Provider value 的改變 {/* **only** Avatar render */ } {({user, setUser}) => }

為什么?為什么把 App 上的全局狀態及設置狀態的方法移到 AppProvider 上,就能避免不必要的渲染?在 props.children 方案中:

// 1. App 本身沒有全局狀態改變,因此  不會重渲染
const App = () => (
 
   
 
);

// 2. Provider value 變化,因此會觸發 Consumer 的監聽函數。

{  /* 3. this.props.children 只是  的引用
  但并不會調用 ,即調用 createElement("Page") */ }
{this.props.children}

雖然,context 解決了數據跨層級傳輸的問題,但是還遺留了一些問題:

Consumer 的回調取值的寫法 { value => <> 不優雅。

單個狀態和狀態改變很好傳遞,但是多個狀態和對應的狀態改變傳遞依舊不方便。

多個全局狀態,如何管理?

沒關系,且看 hooks 閃亮登場,將這些問題一一擊破。

Hooks 概述

考慮到有些朋友不是很了解 hooks,本文先介紹一下 hooks 的基本用法 。Hooks 讓我們可以在 function 組件中使用狀態和生命周期函數,并賦予了一些更強大的功能。這也意味著,在 React 16.8 之后,我們再不需要寫 class 組件。再強調一次,我們再不需要寫 class 組件!

useState: 允許在 function 組件中,聲明和改變狀態。在此之前,只有 class 組件可以。

useEffect:允許在 function 組件中,抽象地使用 React 的生命周期函數。開發者可以使用更函數式的、更清晰的 hooks 的方式。

使用 hooks 對帶有本地狀態的 Avatar 組件進行重構說明:

import React, { useState, useEffect } from "react";

const Avatar = ({ user, setUser }) => {
 // 創建 user 狀態和修改狀態的函數
 const [user, setUser] = useState("崔然");
 
 // 默認 componentDidMount/componentDidUpdate 時會觸發回調
 // 也可以使用第二個參數,指定觸發時機
 useEffect(() => {
   document.title = `當前用戶:${user}`;
});
 
 // 使用 setUser 改變狀態
 return 
setUser("CuiRan")}>{user}
; };

接著,我們繼續了解 context 的 hooks 用法 —— userContext

useContext:更優雅的 context

在 react 引入 hooks 后,使得 context 的消費更簡單了,開發者可以很優雅地直接獲取。下面我們使用 useContextUser 組件進行重構。

// 重構前
const User = () => {
 return (
   
    {({ user, setUser }) => }
   
);
};

// 重構后
const User = () => {
 // 直接獲取,不用回調
 const { user, setUser } = useContext(UserContext);
 return ;
};

就是這么簡單!無論 context 包含什么,是數字、字符串,還是對象、函數,都可以通過useContext訪問它。

useReducer:自帶的狀態管理

當組件同時使用多個useState方法時,需要一個一個的聲明。狀態多了,就一大溜的聲明。比如:

const Avatar = ({ user, setUser }) => {
 const [user, setUser] = useState("崔然");
 const [age, setAge] = useState("18");
 const [gender, setGender] = useState("女");
 const [city, setCity] = useState("北京");
 // more ...
};

useReducer 實際是 useState 的一個變種,解決了上述多個狀態,需要多次使用 useState 的問題。

當你看到 useReducer 時,是不是非常熟悉?想起了redux 中的 reducer 函數。對!React 提供的 useReducer 函數,它就是使用 (use) reducer 函數作為參數。useReducer 接受的 reducer 參數,本質和 redux 的是一樣的。然后 useReducer 會返回 statedispath 方法,返回的 dispath ,本質上和 redux 的也是一樣的。

讓我們使用 useReducer 將帶有本地狀態的 Avatar 組件重構一下:

const reducer = (state, action) => {
 switch (action.type) {
   case "CHANGE_USER":
     return { ...state, user: action.user };
   case "CHANGE_AGE":
     return { ...state, age: action.age };
   // more ...  
   default:
     return state;
}};

const Avatar = ({ user, setUser }) => {
 const [state, dispatch] = useReducer(
   reducer,
  { user: "崔然", age: 18 }
);

 return (
   <>
     
dispatch({ type: "CHANGE_USER", user: "CuiRan" })}> {state.user}
dispatch({ type: "CHANGE_AGE", age: 17 })}> {state.age}
)};

更進一步地,將 useReducer和直接對比 redux 試試,你會發現它們之間驚人的相似:

// react hooks
const [state, dispatch] = useReducer(reducer, [initialArg]);

// redux
const store = createStore(reducer, [initialArg])
const state = store.getState()
const dispatch = store.dispatch

還記得我們再 context 中介紹的 provider 和 consumer 嗎?再聯想一下,它們的作用不就是和 react-redux 中的 provider 和 connect 一模一樣 —— 將數據跨層級的進行傳遞!

// react hooks

 

// ... 跨層級傳遞 ...
const { state, dispacth } = useContext(GolbleContext);

// react-redux

 

// ... 跨層級傳遞 ...
connect(mapStateToProps, actionCreators)(ConsumerComponent)

到現在為止,react 可謂是自帶了大半個 redux 的 API 了。那么我們不就可以把 redux 的狀態管理思路直接搬過來即可。

最后,只需要將全局狀態放到在 App 組件的頂層。最終的示例:

const Avatar = ({{ state, dispatch }) => {// ...})
// 使用全局狀態和 dispatch
const User = () => {
 const { state, dispatch } = useContext(UserContext);
 return ;
};

// 生成全局狀態和 dispatch
const reducer = (state, action) => {// ...};
const AppProvider = ({ children }) => {
 const [state, dispatch] = useReducer(reducer, { user: "崔然", age: 18 });

 return (
   
    {children}
   
)};

完整示例見:https://github.com/jiangleo/h...

結論

在 hooks 和 context 出現之前,react 缺乏自帶的全局狀態管理能力。即便很小的應用,一旦要用到全局狀態,要么使用 props 多層級的進行傳輸,要么就只能引入 redux 等第三方狀態管理工具。

在 hooks 和 context 出現之后,react 自身提供了一種簡單的全局狀態管理的能力。如果你的項目比較簡單,只有少部分狀態需要提升到全局,大部分組件依舊通過本地狀態來進行管理。這時,使用 hooks + context 進行狀態管理的是強烈推薦的。打蒼蠅,用不著大炮。

此外,我們也觀察到,社區中一些新型的基于 hooks + context 的狀態管理庫正在快速崛起,比如 easy-peasy、constate。另一方面,成熟的 redux 也在 7.x 版本,開始引入 hooks API 開始升級。我們也會持續保持關注,探索 hooks 時代狀態管理的最佳實踐。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/105348.html

相關文章

  • React組件設計實踐總結05 - 狀態管理

    摘要:要求通過要求數據變更函數使用裝飾或放在函數中,目的就是讓狀態的變更根據可預測性單向數據流。同一份數據需要響應到多個視圖,且被多個視圖進行變更需要維護全局狀態,并在他們變動時響應到視圖數據流變得復雜,組件本身已經無法駕馭。今天是 520,這是本系列最后一篇文章,主要涵蓋 React 狀態管理的相關方案。 前幾篇文章在掘金首發基本石沉大海, 沒什么閱讀量. 可能是文章篇幅太長了?掘金值太低了? ...

    ideaa 評論0 收藏0
  • 使用react hooks實現自己的context-redux

    摘要:首發自我的博客,歡迎注如要運行本文的代碼,請先確認自己的版本已支持出來已經有段時間了,本文不對的具體用法作介紹,而是使用實現一個簡易的基于的使用實現初版自帶了供我們使用,它接受兩個參數,一是函數,二是初始,并返回和函數,如下這個函數自己實現 首發自我的github博客,歡迎star 注:如要運行本文的代碼,請先確認自己的react版本已支持hooks react hooks出來已經有段...

    Jackwoo 評論0 收藏0
  • react hooks初探

    摘要:可以在不改變組件層級的前提下將帶有狀態的邏輯抽離出來。因此在中增加了一個特性,允許傳入的函數再返回一個函數,這個返回函數的執行時機是下一次觸發這個前,以及組件卸載前。當第二個參數為空數組時,返回函數進行清理工作只會在組件卸載時執行。 hooks是什么 hooks是react16.8版本中新增的特性,它讓我們能夠在不寫class的情況下使用狀態和其他react特性。也就是說現在我們可以在...

    dendoink 評論0 收藏0
  • 30分鐘精通React今年最勁爆的新特性——React Hooks

    摘要:所以我們做的事情其實就是,聲明了一個狀態變量,把它的初始值設為,同時提供了一個可以更改的函數。 你還在為該使用無狀態組件(Function)還是有狀態組件(Class)而煩惱嗎? ——擁有了hooks,你再也不需要寫Class了,你的所有組件都將是Function。 你還在為搞不清使用哪個生命周期鉤子函數而日夜難眠嗎? ——擁有了Hooks,生命周期鉤子函數可以先丟一邊了。 你在還...

    icattlecoder 評論0 收藏0
  • React Hooks實現異步請求實例—useReducer、useContext和useEffec

    摘要:本文是學習了年新鮮出爐的提案之后,針對異步請求數據寫的一個案例。注意,本文假設了你已經初步了解的含義了,如果不了解還請移步官方文檔。但不要忘記和上下文對象可以看做是寫法的以及三個鉤子函數的組合。 本文是學習了2018年新鮮出爐的React Hooks提案之后,針對異步請求數據寫的一個案例。注意,本文假設了:1.你已經初步了解hooks的含義了,如果不了解還請移步官方文檔。(其實有過翻譯...

    Code4App 評論0 收藏0

發表評論

0條評論

tommego

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<