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

資訊專(zhuān)欄INFORMATION COLUMN

react hooks初探

dendoink / 2982人閱讀

摘要:可以在不改變組件層級(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)在我們可以在函數(shù)組件中進(jìn)行狀態(tài)管理了。

hooks解決了什么問(wèn)題

組件中帶狀態(tài)的邏輯很難復(fù)用

在hooks之前解決這個(gè)問(wèn)題的手段是render props和高階組件。但是這些方法都需要我們?nèi)バ薷慕M件層級(jí)關(guān)系,讓代碼變得很繁瑣。
hooks可以在不改變組件層級(jí)的前提下將帶有狀態(tài)的邏輯抽離出來(lái)。

復(fù)雜組件讓人難以理解

原先用class寫(xiě)的組件集成了許多生命周期函數(shù),這些生命周期函數(shù)中又包含了許多互不相關(guān)的邏輯,比如接口請(qǐng)求,事件綁定等等。這導(dǎo)致組件邏輯復(fù)雜之后難以理解也難以測(cè)試。
hooks可以將復(fù)雜組件的邏輯拆分成更小的函數(shù),這些函數(shù)只負(fù)責(zé)單一的邏輯。拆分后的優(yōu)點(diǎn)是易懂易測(cè)試。

class本身存在的問(wèn)題

盡管class已經(jīng)是一個(gè)語(yǔ)法糖了,但是react的開(kāi)發(fā)者認(rèn)為this是一個(gè)很麻煩的東西,我們?cè)谟胏lass寫(xiě)組件前必須先搞清楚this的工作原理。另外class組件在react編譯過(guò)程中也存在一些問(wèn)題,如壓縮率并不是很好,熱加載不穩(wěn)定等等。
hooks可以讓我們?cè)诤瘮?shù)組件中管理狀態(tài)。盡管完全拋棄class組件還為時(shí)尚早,但是有了hooks我們使用class組件的機(jī)會(huì)將越來(lái)越少。

幾個(gè)常用的hooks useState

基本用法:

import React, { useState } from "react";
export default function Foo() {
    const [selectedKey, setSelectedKey] = useState("");
    const someHandler = () => { setSelectedKey("1") };
    ...
    return ...;
}

上面例子中,useState函數(shù)會(huì)返回一個(gè)數(shù)組,數(shù)組第一項(xiàng)是我們定義的一個(gè)狀態(tài)selectedKey,第二項(xiàng)是修改這個(gè)狀態(tài)的函數(shù),而userState接收的參數(shù)就是這個(gè)狀態(tài)的初始值。當(dāng)我們使用setSelectedKey修改狀態(tài)時(shí),react會(huì)重新渲染該組件,效果跟setState一樣。
這段代碼改成class的寫(xiě)法是這樣的:

import React, { Component } from "react";
export default class Foo extends Component {
    state = {
        selectedKey: ""
    }
    someHandler = () => {
        this.setState({selectedKey: "1"});
    }
    ...
    render() {
        return ...;
    }
}

區(qū)別:

使用class時(shí),我們把組件的所有狀態(tài)都放在state這個(gè)對(duì)象中;而一個(gè)useState只定義一個(gè)狀態(tài)量,組件有幾個(gè)狀態(tài)變量就寫(xiě)幾行useState

setState是將新?tīng)顟B(tài)merge到老狀態(tài)中,而useState返回的函數(shù)setSelectedKey是將新?tīng)顟B(tài)替換老狀態(tài),因?yàn)橐粋€(gè)useState只定義一個(gè)狀態(tài)量所以這邊直接替換是沒(méi)有問(wèn)題的

useEffect

顧名思義,useEffect就是去做一些有副作用的事。默認(rèn)情況下useEffect接收一個(gè)函數(shù)作為參數(shù),在每次render結(jié)束后react會(huì)去執(zhí)行這個(gè)函數(shù),效果相當(dāng)于componentDidMount和componentDidUpdate的組合。
下面這段代碼表示每次渲染后將狀態(tài)selectedKey的值設(shè)為home:

import React, { useState, useEffect } from "react";
export default function Foo() {
    const [selectedKey, setSelectedKey] = useState("");
    useEffect(()=> {
        setSelectedKey("home");
    });
    ...
    return ...;
}

useEffect的功能還不止這么簡(jiǎn)單,當(dāng)我們進(jìn)行某些副作用操作后,往往需要在組件卸載前做一些清理工作,比如清除定時(shí)器,解綁事件監(jiān)聽(tīng)器等等。因此react在useEffect中增加了一個(gè)特性,允許傳入的函數(shù)再返回一個(gè)函數(shù),這個(gè)返回函數(shù)的執(zhí)行時(shí)機(jī)是下一次觸發(fā)這個(gè)useEffect前,以及組件卸載前。
如果我們只想在組件卸載前進(jìn)行一些清理工作,那就要用到uesEffect的第二個(gè)參數(shù)了。第二個(gè)參數(shù)是一個(gè)數(shù)組,里面可以放這個(gè)副作用的依賴(lài),作用是控制這個(gè)副作用執(zhí)行的時(shí)機(jī),只有當(dāng)依賴(lài)發(fā)生變化的時(shí)候才會(huì)執(zhí)行這個(gè)副作用。當(dāng)?shù)诙€(gè)參數(shù)為空數(shù)組時(shí),返回函數(shù)(進(jìn)行清理工作)只會(huì)在組件卸載時(shí)執(zhí)行。
下面這個(gè)例子的作用是在組件首次渲染后以及props.source的值發(fā)生變化后執(zhí)行subscribe( ),在下一次執(zhí)行subscribe( )前以及組件卸載前執(zhí)行unsubscribe( ):

useEffect(
  () => {
    const subscription = props.source.subscribe();
    return () => {
      subscription.unsubscribe();
    };
  },
  [props.source]
);

使用useEffect可以模擬react的某些生命周期函數(shù)

模擬componentDidMount
useEffect(() => {
    // 這里在mount時(shí)執(zhí)行一次
}, []);
模擬componentWillUnmount
useEffect(() => {
    // 這里在mount時(shí)執(zhí)行一次
    return () => {
    // 這里在unmount時(shí)執(zhí)行一次
    }
}, []);
模擬componentDidUpdate
// useRef會(huì)返回一個(gè)對(duì)象,這個(gè)對(duì)象有個(gè)current屬性,值為傳給useRef的參數(shù)
// useRef在組件生命周期中只初始化一次,之后它會(huì)幫我們保存返回的對(duì)象
const mounting = useRef(true);
useEffect(() => {
    if (mounting.current) {
    mounting.current = false; // 對(duì)current的修改會(huì)被useRef保存,但修改不會(huì)引起重新渲染
    } else {
    // 這里只在update時(shí)執(zhí)行
    }
});
舉例

需求:使用antd的menu組件實(shí)現(xiàn)一個(gè)側(cè)邊欄,類(lèi)似下面的樣子,當(dāng)用戶輸入不同url時(shí)側(cè)邊欄需要聯(lián)動(dòng)

實(shí)現(xiàn):

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

export default function Sider() {
    const [selectedKey, setSelectedKey] = useState("");
    const [openKeys, setOpenKeys] = useState([]);
    // 組件更新時(shí)根據(jù)url更新選中的菜單項(xiàng)
    useEffect(() => {
        const key = getSelectedKey(); // 根據(jù)url得到選中的菜單項(xiàng)
        setSelectedKey(key);
    });
    // 組件mount時(shí)根據(jù)url自動(dòng)展開(kāi)子菜單
    useEffect(() => {
        const key = getOpenKey(); // 根據(jù)url得到應(yīng)該展開(kāi)的菜單
        setOpenKeys([key]);
    }, []);
    ...
    return (
         setOpenKeys(openKeys)}
        >
        ...
        
    );
}

分析:

組件使用useState定義了兩個(gè)狀態(tài)量:selectedKey和openKeys;

第一個(gè)useEffect用于更新selectedKey,它會(huì)在每次render后從url中獲取當(dāng)前選中的菜單項(xiàng),然后更新selectedKey;

第二個(gè)useEffect用于首次進(jìn)入網(wǎng)站時(shí),從url中獲取應(yīng)該展開(kāi)的菜單并更新openKeys,它只在組件創(chuàng)建時(shí)執(zhí)行,相當(dāng)于componentDidMount;

當(dāng)用戶點(diǎn)擊父菜單想要展開(kāi)或收起時(shí),通過(guò)onOpenChange事件來(lái)觸發(fā)openKeys的更新;

當(dāng)用戶點(diǎn)擊子菜單想要選中時(shí),會(huì)先觸發(fā)路由跳轉(zhuǎn)(這個(gè)邏輯無(wú)法從代碼中獲取,請(qǐng)自行腦補(bǔ)),路由改變會(huì)引發(fā)改組件重新渲染,繼而觸發(fā)第一個(gè)useEffect來(lái)更新selectedKey。

自定義hooks

文章開(kāi)頭已經(jīng)講到了hooks可以很方便的實(shí)現(xiàn)帶狀態(tài)的邏輯復(fù)用。
下面是一個(gè)簡(jiǎn)單的自定義hooks,功能是請(qǐng)求接口并返回?cái)?shù)據(jù):

import { useState, useEffect } from "react";

export default function useUserInfo() {
    const [userInfo, setUserInfo] = useState(null);
    useEffect(() => {
        fetch("https://react.hooks.com/api/userinfo").then(
            data => {
                setUserInfo(data);
            },
        );
    }, []);
    return userInfo;
}

使用也很簡(jiǎn)單,當(dāng)Home組件加載時(shí)會(huì)通過(guò)useUserInfo這個(gè)自定義hooks去請(qǐng)求接口,接口數(shù)據(jù)返回時(shí)Home組件會(huì)自動(dòng)更新:

import React from "react";
import useUserInfo from "../../hooks/useUserInfo";

export default function Home() {
    const userInfo = useUserInfo();
    
    return 
{userInfo}
; }
hooks + context進(jìn)行全局狀態(tài)管理

react提供了useContext這個(gè)hooks使得在函數(shù)組件中使用context變得更加方便。
如果項(xiàng)目沒(méi)有復(fù)雜到需要上redux,可以使用下面的方法進(jìn)行全局狀態(tài)管理。
首先創(chuàng)建一個(gè)context:

// globalContext.js
import React from "react";

export default React.createContext({
    musicianPlan: "1",
    language: "zh",
    changeMusicianPlan: () => {},
    changeLanguage: () => {},
});

然后定義一個(gè)高階組件,用于管理context中的狀態(tài):

// globalState.jsx
import React, { useState } from "react";
import GlobalContext from "./globalContext";

export default function GlobalState(props) {
    const [musicianPlan, setMusicianPlan] = useState("1");
    const [language, setLanguage] = useState("zh");
    const changeMusicianPlan = planId => {
        setMusicianPlan(planId);
    };
    const changeLanguage = lang => {
        setLanguage(lang);
    };
    return (
        
            {props.children}
        
    );
}

將這個(gè)高階組件放到組件樹(shù)的頂層:

// app.jsx
import React from "react";
import GlobalState from "./context/globalState";

export default function App() {
    return (
        
            
                ...
            
        
    );
}

在Header組件中用useContext這個(gè)hooks獲取到context,然后調(diào)用changeMusicianPlan方法來(lái)改變?nèi)譅顟B(tài)musicianPlan:

import React, { useContext, ReactElement } from "react";
import { Select } from "antd";
import GlobalContext from "../../context/globalContext";

const Option = Select.Option;

export default function Header() {
    const globalContext = useContext(GlobalContext);
    return (
        
    );
}

在Home組件中同樣使用useContext獲取context,然后使用全局狀態(tài)musicianPlan進(jìn)行動(dòng)態(tài)渲染:

import React, { useContext } from "react";
import GlobalContext from "../../context/globalContext";

export default function Home() {
    const globalContext = useContext(GlobalContext);
    return 
{globalContext.musicianPlan}
; }

當(dāng)然上面的方法也可以用于某個(gè)局部組件樹(shù)的狀態(tài)管理,將狀態(tài)進(jìn)行拆分管理不僅提高運(yùn)行效率也更清晰易懂。

使用hooks的注意事項(xiàng)

hooks只能在組件內(nèi)部的最頂層調(diào)用,不能將其放在循環(huán)語(yǔ)句、條件語(yǔ)句或者子函數(shù)內(nèi);

hooks只能在函數(shù)組件或自定義hooks中使用;

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

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

相關(guān)文章

  • 解讀React源碼(一):初探React源碼

    摘要:前言的基本概念組件的構(gòu)建方法以及高級(jí)用法這背后的一切如何運(yùn)轉(zhuǎn)深入內(nèi)部的實(shí)現(xiàn)機(jī)制和原理初探源碼代碼組織結(jié)構(gòu)包含一系列的工具方法插件包含一系列同構(gòu)方法包含一些公用或常用方法如等包含一些測(cè)試方法等包含一些邊界錯(cuò)誤的測(cè)試用例是代碼的核心部分它包含了 前言 React的基本概念,API,組件的構(gòu)建方法以及高級(jí)用法,這背后的一切如何運(yùn)轉(zhuǎn),深入Virtual DOM內(nèi)部的實(shí)現(xiàn)機(jī)制和原理. 初探Rea...

    Eminjannn 評(píng)論0 收藏0
  • React 初探

    摘要:各個(gè)組件維護(hù)自己的狀態(tài)和,當(dāng)狀態(tài)變更,自動(dòng)重新渲染整個(gè)組件。形式的定義的組件是以的形式來(lái)創(chuàng)建的組件的,是目前極為推薦的創(chuàng)建有狀態(tài)組件的方式,最終會(huì)取代形式相對(duì)于可以更好實(shí)現(xiàn)代碼復(fù)用。組件名稱(chēng)首字母必須大寫(xiě)。變量名用包裹,且不能加雙引號(hào)。 目前在前端開(kāi)發(fā)領(lǐng)域,框架Angular、react和vue占據(jù)著主流的地位而且可能會(huì)持續(xù)比較長(zhǎng)的一段時(shí)間。三門(mén)框架中,從數(shù)據(jù)綁定機(jī)制來(lái)看,vue和an...

    levy9527 評(píng)論0 收藏0
  • React 初探

    摘要:各個(gè)組件維護(hù)自己的狀態(tài)和,當(dāng)狀態(tài)變更,自動(dòng)重新渲染整個(gè)組件。形式的定義的組件是以的形式來(lái)創(chuàng)建的組件的,是目前極為推薦的創(chuàng)建有狀態(tài)組件的方式,最終會(huì)取代形式相對(duì)于可以更好實(shí)現(xiàn)代碼復(fù)用。組件名稱(chēng)首字母必須大寫(xiě)。變量名用包裹,且不能加雙引號(hào)。 目前在前端開(kāi)發(fā)領(lǐng)域,框架Angular、react和vue占據(jù)著主流的地位而且可能會(huì)持續(xù)比較長(zhǎng)的一段時(shí)間。三門(mén)框架中,從數(shù)據(jù)綁定機(jī)制來(lái)看,vue和an...

    trilever 評(píng)論0 收藏0
  • react-redux初探理解

    摘要:它的作用就是像它的名字那樣,建立一個(gè)從外部的對(duì)象到組件的對(duì)象的映射關(guān)系。比如表示從整個(gè)的表示當(dāng)前組件容器的用來(lái)建立組件的參數(shù)到方法的映射比如表示它定義了哪些用戶的操作應(yīng)該當(dāng)作,傳給。 最近做的項(xiàng)目加入了react-redux,對(duì)react-redux一直沒(méi)理解透徹,最近有時(shí)間把react-redux梳理了一番,希望能夠幫助到大家, 首先有這幾個(gè)文件,action,reducer,sag...

    ziwenxie 評(píng)論0 收藏0
  • 初探react技術(shù)棧(一)

    摘要:相信用的同學(xué)也不少找到函數(shù)在其中中添加啟用編譯。。。react 最近已經(jīng)開(kāi)始使用react技術(shù)棧了,從頭開(kāi)始搭建項(xiàng)目,有必要的記錄一下配置的過(guò)程以及項(xiàng)目分層的思路,這次后臺(tái)項(xiàng)目采用的主要采用react-create-app腳手架以及Ant DesignUI 以及多語(yǔ)言react-intl create-react-app 這是官方維護(hù)的腳手架應(yīng)用 我們一般也采用這個(gè) $ npm or c...

    劉玉平 評(píng)論0 收藏0

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

0條評(píng)論

dendoink

|高級(jí)講師

TA的文章

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