亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專(zhuān)欄INFORMATION COLUMN

Hooks + Context:狀態(tài)管理的新選擇

tommego / 3384人閱讀

摘要:用戶(hù)點(diǎn)擊改變?nèi)譅顟B(tài)崔然渲染整顆組件樹(shù)有沒(méi)有解決方案呢當(dāng)然有創(chuàng)建一個(gè)只接收的新組件,并將組件中的邏輯都移到組件中。最終的示例使用全局狀態(tài)和生成全局狀態(tài)和崔然完整示例見(jiàn)結(jié)論在和出現(xiàn)之前,缺乏自帶的全局狀態(tài)管理能力。

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

本文首先會(huì)對(duì)官方的 context 作簡(jiǎn)單介紹,并搭建一個(gè)十分簡(jiǎn)單的使用全局狀態(tài)的應(yīng)用。然后再對(duì) hooks 的基本 API useState useEffect 做基本介紹。接著使用 useContext hooks 對(duì)應(yīng)用進(jìn)行重構(gòu),讓 context 的使用變得更優(yōu)雅。再使用 useReducer hooks 來(lái)管理多個(gè)狀態(tài)。最后,待充分理解 hooks 和 context 之后,我們將它們搭配起來(lái)用,對(duì)整個(gè)應(yīng)用進(jìn)行狀態(tài)管理。

Context 概述

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

例如,一個(gè) Page 組件包含全局狀態(tài) user ,需要經(jīng)過(guò)多次props的傳遞,層級(jí)很深的 Avatar 組件才能使用它。


// ... render ...

// ... render ...

// ... render ...
Context :跨層級(jí)傳遞數(shù)據(jù)

Context 提供了一種方法,解決了全局?jǐn)?shù)據(jù)傳遞的問(wèn)題,使得組件之間不用顯式地通過(guò) props 傳遞數(shù)據(jù)。

React.createContext: 創(chuàng)建一個(gè) Context 對(duì)象,該對(duì)象擁有 Provider 和 Consumer 屬性。

Context.Provider: 接受一個(gè) value 參數(shù),在 value 參數(shù)更新的時(shí)候通知 Consumer。

Context.Consumer: 訂閱 value 參數(shù)的改變。一旦 value 參數(shù)改變,就會(huì)觸發(fā)它的回調(diào)函數(shù)。

使用 context 重構(gòu)的之后,跨層級(jí)傳遞數(shù)據(jù)就變得容易很多:

// 創(chuàng)建一個(gè) context
const UserContext = React.createContext();

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

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

 render() {
   // 設(shè)置 context 當(dāng)前值為 {user, setUser}
   return (
     
       
     
  );
}
}

// ... Page render ...

// ... PageLayout render ...

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

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

但是,在使用 context 時(shí),有些寫(xiě)代碼的小技巧,需要特別注意。不然在全局狀態(tài)改變時(shí), Provider 的所有后代組件都會(huì)重新渲染。例如,用戶(hù)點(diǎn)擊 Avatar 組件后,將 崔然 更新為 CuiRan,這時(shí)會(huì)調(diào)用根組件的 setUser 方法。根組件 setState({ user }) 更新?tīng)顟B(tài),會(huì)導(dǎo)致整顆組件樹(shù)重新渲染。

const Avatar = ({ user, setUser }) => {
 // 用戶(hù)點(diǎn)擊改變?nèi)譅顟B(tài)
 return 
setUser("CuiRan")}>{user}
; }; class App extends React.Component { state = { user: "崔然" }; setUser = user => { this.setState({ user }); }; // ... 渲染整顆組件樹(shù) }

有沒(méi)有解決方案呢?當(dāng)然有!

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

const Avatar = ({ user, setUser }) => {
 // 用戶(hù)點(diǎn)擊改變?nèi)譅顟B(tài)
 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 監(jiān)聽(tīng)到 Provider value 的改變 {/* **only** Avatar render */ } {({user, setUser}) => }

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

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

// 2. Provider value 變化,因此會(huì)觸發(fā) Consumer 的監(jiān)聽(tīng)函數(shù)。

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

雖然,context 解決了數(shù)據(jù)跨層級(jí)傳輸?shù)膯?wèn)題,但是還遺留了一些問(wèn)題:

Consumer 的回調(diào)取值的寫(xiě)法 { value => <> 不優(yōu)雅。

單個(gè)狀態(tài)和狀態(tài)改變很好傳遞,但是多個(gè)狀態(tài)和對(duì)應(yīng)的狀態(tài)改變傳遞依舊不方便。

多個(gè)全局狀態(tài),如何管理?

沒(méi)關(guān)系,且看 hooks 閃亮登場(chǎng),將這些問(wèn)題一一擊破。

Hooks 概述

考慮到有些朋友不是很了解 hooks,本文先介紹一下 hooks 的基本用法 。Hooks 讓我們可以在 function 組件中使用狀態(tài)和生命周期函數(shù),并賦予了一些更強(qiáng)大的功能。這也意味著,在 React 16.8 之后,我們?cè)俨恍枰獙?xiě) class 組件。再?gòu)?qiáng)調(diào)一次,我們?cè)俨恍枰獙?xiě) class 組件!

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

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

使用 hooks 對(duì)帶有本地狀態(tài)的 Avatar 組件進(jìn)行重構(gòu)說(shuō)明:

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

const Avatar = ({ user, setUser }) => {
 // 創(chuàng)建 user 狀態(tài)和修改狀態(tài)的函數(shù)
 const [user, setUser] = useState("崔然");
 
 // 默認(rèn) componentDidMount/componentDidUpdate 時(shí)會(huì)觸發(fā)回調(diào)
 // 也可以使用第二個(gè)參數(shù),指定觸發(fā)時(shí)機(jī)
 useEffect(() => {
   document.title = `當(dāng)前用戶(hù):${user}`;
});
 
 // 使用 setUser 改變狀態(tài)
 return 
setUser("CuiRan")}>{user}
; };

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

useContext:更優(yōu)雅的 context

在 react 引入 hooks 后,使得 context 的消費(fèi)更簡(jiǎn)單了,開(kāi)發(fā)者可以很優(yōu)雅地直接獲取。下面我們使用 useContext 對(duì) User 組件進(jìn)行重構(gòu)。

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

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

就是這么簡(jiǎn)單!無(wú)論 context 包含什么,是數(shù)字、字符串,還是對(duì)象、函數(shù),都可以通過(guò)useContext訪問(wèn)它。

useReducer:自帶的狀態(tài)管理

當(dāng)組件同時(shí)使用多個(gè)useState方法時(shí),需要一個(gè)一個(gè)的聲明。狀態(tài)多了,就一大溜的聲明。比如:

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

useReducer 實(shí)際是 useState 的一個(gè)變種,解決了上述多個(gè)狀態(tài),需要多次使用 useState 的問(wèn)題。

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

讓我們使用 useReducer 將帶有本地狀態(tài)的 Avatar 組件重構(gòu)一下:

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}
)};

更進(jìn)一步地,將 useReducer和直接對(duì)比 redux 試試,你會(huì)發(fā)現(xiàn)它們之間驚人的相似:

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

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

還記得我們?cè)?context 中介紹的 provider 和 consumer 嗎?再聯(lián)想一下,它們的作用不就是和 react-redux 中的 provider 和 connect 一模一樣 —— 將數(shù)據(jù)跨層級(jí)的進(jìn)行傳遞!

// react hooks

 

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

// react-redux

 

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

到現(xiàn)在為止,react 可謂是自帶了大半個(gè) redux 的 API 了。那么我們不就可以把 redux 的狀態(tài)管理思路直接搬過(guò)來(lái)即可。

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

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

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

 return (
   
    {children}
   
)};

完整示例見(jiàn):https://github.com/jiangleo/h...

結(jié)論

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

在 hooks 和 context 出現(xiàn)之后,react 自身提供了一種簡(jiǎn)單的全局狀態(tài)管理的能力。如果你的項(xiàng)目比較簡(jiǎn)單,只有少部分狀態(tài)需要提升到全局,大部分組件依舊通過(guò)本地狀態(tài)來(lái)進(jìn)行管理。這時(shí),使用 hooks + context 進(jìn)行狀態(tài)管理的是強(qiáng)烈推薦的。打蒼蠅,用不著大炮。

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

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/105348.html

相關(guān)文章

  • React組件設(shè)計(jì)實(shí)踐總結(jié)05 - 狀態(tài)管理

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

    ideaa 評(píng)論0 收藏0
  • 使用react hooks實(shí)現(xiàn)自己的context-redux

    摘要:首發(fā)自我的博客,歡迎注如要運(yùn)行本文的代碼,請(qǐng)先確認(rèn)自己的版本已支持出來(lái)已經(jīng)有段時(shí)間了,本文不對(duì)的具體用法作介紹,而是使用實(shí)現(xiàn)一個(gè)簡(jiǎn)易的基于的使用實(shí)現(xiàn)初版自帶了供我們使用,它接受兩個(gè)參數(shù),一是函數(shù),二是初始,并返回和函數(shù),如下這個(gè)函數(shù)自己實(shí)現(xiàn) 首發(fā)自我的github博客,歡迎star 注:如要運(yùn)行本文的代碼,請(qǐng)先確認(rèn)自己的react版本已支持hooks react hooks出來(lái)已經(jīng)有段...

    Jackwoo 評(píng)論0 收藏0
  • react hooks初探

    摘要:可以在不改變組件層級(jí)的前提下將帶有狀態(tài)的邏輯抽離出來(lái)。因此在中增加了一個(gè)特性,允許傳入的函數(shù)再返回一個(gè)函數(shù),這個(gè)返回函數(shù)的執(zhí)行時(shí)機(jī)是下一次觸發(fā)這個(gè)前,以及組件卸載前。當(dāng)?shù)诙€(gè)參數(shù)為空數(shù)組時(shí),返回函數(shù)進(jìn)行清理工作只會(huì)在組件卸載時(shí)執(zhí)行。 hooks是什么 hooks是react16.8版本中新增的特性,它讓我們能夠在不寫(xiě)class的情況下使用狀態(tài)和其他react特性。也就是說(shuō)現(xiàn)在我們可以在...

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

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

    icattlecoder 評(píng)論0 收藏0
  • React Hooks實(shí)現(xiàn)異步請(qǐng)求實(shí)例—useReducer、useContext和useEffec

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

    Code4App 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

tommego

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<