React18(函數(shù)式開發(fā))+Ts入門開發(fā)(三)初識Hooks以及同步獲取State的值

再此之前你已經(jīng)學(xué)習(xí)了:
React18(函數(shù)式開發(fā))+Ts入門開發(fā)(一)創(chuàng)建Ts項(xiàng)目使用SCSS店展、antdUI庫
React18(函數(shù)式開發(fā))+Ts入門開發(fā)(二)路由配置以及路由的基礎(chǔ)使用

今天第三講就講講復(fù)制傳值以及hooks的實(shí)際應(yīng)用吧。
PS:此頁面我已經(jīng)事先創(chuàng)建好,并且建好路由了。不會創(chuàng)建頁面建路由的看上面一二兩篇筹麸。本篇就不重復(fù)講述怎么創(chuàng)建頁面和路由了炕泳。

一 初識useEffect,先簡單介紹下它是什么

為什么React18后函數(shù)式開發(fā)火了苞七,就是因?yàn)?8之前函數(shù)式組件是沒有生命周期的,導(dǎo)致它不能滿足某些特殊需求挪丢。而有了hooks后蹂风,他就有了自己的生命周期。
當(dāng)然乾蓬,我這里只是簡單介紹一下以及我們開發(fā)常用的惠啄。更詳細(xì)的需要看官方文檔了。

1. 模擬componentDidMount第一次渲染
useEffect(() => {
    console.log('');
}, []) // 第二個(gè)參數(shù)為空時(shí)只會在第一次渲染時(shí)執(zhí)行
2. 模擬componentDidUpdate
useEffect(() => {
    console.log('n變化了');
}, [n]) // 第二個(gè)參數(shù)為要監(jiān)聽的數(shù)據(jù)

// 不傳第二個(gè)參數(shù),則會在 state 的任意一個(gè)屬性改變時(shí)都會觸發(fā)該函數(shù)回調(diào)
useEffect(() => {
    console.log('任意屬性變化');
})
3. 模擬componentWillUnmount
useEffect(() => {
    console.log('任意屬性變了');
    return () => {
        console.log('該組件要銷毀了');
    }
})

二 初識useState 我們先聲明兩個(gè)變量撵渡,并且賦值融柬。以及useEffect 的大概使用

1. 基礎(chǔ)賦值
import { useState, useEffect } from "react";

// 父組件
function HooksDemo() {
    // 定義一個(gè) num 初始為 0
    // 定義一個(gè) isBoolean 初始為 false
    const [num, setNum] = useState(0);
    const [isBoolean,setBoolean] = useState(false);
    // 等同于Vue
    // data() {
    //     return {
    //         num:0,
    //         isBoolean:false,
    //     }
    // }
    
    // 初始化執(zhí)行
    useEffect(()=>{
        setNum(5);
        console.log(num); // 你以為是輸出5,實(shí)際是 0    也就是上一次的值
        setBoolean(true)  
        console.log(isBoolean); // 你以為是輸出true姥闭,實(shí)際是 false      也就是上一次的值
    },[]);
    // 等同于Vue
    // mounted(){
    //     this.num = 5;
    //     console.log(num); // 輸出5
    //     this.isBoolean = true;
    //     console.log(num); // 輸出true
    // }
    return <div className="home">hooksDemo 示例</div>;
}

export default HooksDemo;
2. 其他賦值

有時(shí)候我們可能定義的是一個(gè)對象丹鸿,或者其他的,只需要改變其中的某一個(gè)值棚品。并不需要全部改變靠欢。
這種情況怎么辦呢?

const [user,setUser] = useState({name:"zs",age:20});

// demo1
setUser(Object.assign(user,{age:18})); // {name: 'zs', age: 18}

// demo2
const changeUser = (num: number) => {
    setUser((state) => {
        let { name, age } = state;
        age = num;
        return {
            name,
            age,
        };
    });
};

三 通過useCallback同步獲取Set后的值

從上面我們發(fā)現(xiàn)一個(gè)問題铜跑,就是當(dāng)我們set值后门怪,無法同步獲取。其實(shí)React中的setState本身執(zhí)行的過程和代碼是同步的(比如你HTML里{num} 顯示的就是5)锅纺,只是因?yàn)?React 框架本身的性能優(yōu)化機(jī)制而導(dǎo)致的掷空。
React 中合成事件和生命周期函數(shù)的調(diào)用順序在更新之前,導(dǎo)致在合成事件和生命周期函數(shù)中無法立刻得到更新后的值囤锉,形成了異步的形式坦弟。說白了就是你無法立即獲取最新的值。也就是set后的值官地。下面看示例酿傍。

示例一
// css
//.active {
//    color: red;
//}
// 父組件
function HooksDemo() {
    // 定義一個(gè) tabList
    const [tabList] = useState([
        {
            name: "全部",
            code: "all",
        },
        {
            name: "已開啟",
            code: "open",
        },
        {
            name: "已關(guān)閉",
            code: "close",
        },
    ]);
    const [cutTab, setCutTat] = useState("");
    useEffect(() => {
        // 這里不要問為什么不初始化 useState("all"); 實(shí)際開發(fā)中這個(gè)值可能是其他組件傳過來的。
        setCutTat("all");
        console.log(cutTab,'看輸出'); // 輸出 ""
    }, []);
    return (
        <div className="home">
            <ul>
                {tabList.map((tab, inx) => {
                    return <li key={inx} className={`${cutTab == tab.code ? 'active': ''}`}>{tab.name}</li>;
                })}
            </ul>
        </div>
    );
}

export default HooksDemo;

image.png

此時(shí)驱入,初始化的時(shí)候console.log(cutTab,'看輸出'); // 輸出 ""赤炒,但是頁面實(shí)際卻高亮第一個(gè)了。這就我上面說的它再執(zhí)行的過程實(shí)際是同步的亏较。只是由于機(jī)制問題莺褒,你輸出的時(shí)候他就變成異步了。那么此時(shí)會出現(xiàn)什么問題呢雪情?我們看下一個(gè)示例

示例二
import "./index.scss";
import { useState, useEffect } from "react";

// 父組件
function HooksDemo() {
    // 定義一個(gè) tabList
    const [tabList] = useState([
        {
            name: "全部",
            code: "all",
        },
        {
            name: "已開啟",
            code: "open",
        },
        {
            name: "已關(guān)閉",
            code: "close",
        },
    ]);
    const [cutTab, setCutTat] = useState("");
    useEffect(() => {
        // 這里不要問為什么不初始化 useState("all"); 實(shí)際開發(fā)中這個(gè)值可能是其他組件傳過來的遵岩。
        setCutTat("all");
        console.log(cutTab, "看輸出"); // 輸出 ""
    }, []);
    // 頁簽切換
    const tabChange = (tab: any) => {
        if (tab.code == cutTab) {
            return;
        }
        setCutTat(tab.code);
        // 通過請求獲取數(shù)據(jù)
        getListData();
    };
    // 請求獲取數(shù)據(jù)
    const getListData = () => {
        // 此時(shí)拿到的 code 其實(shí)是上一次的。
        console.log(cutTab) // 輸出的是上一次的巡通。
    };
    return (
        <div className="home">
            <ul>
                {tabList.map((tab, inx) => {
                    return (
                        <li
                            key={inx}
                            className={`${cutTab == tab.code ? "active" : ""}`}
                            onClick={(e) => tabChange(tab)}
                        >
                            {tab.name}
                        </li>
                    );
                })}
            </ul>
        </div>
    );
}

export default HooksDemo;

當(dāng)然有的朋友就要問了尘执,我為什么要setCutTat(tab.code);后再掉接口,不能直接掉接口getListData(tab.code);把參數(shù)傳過去嗎扁达?答案是可以的正卧。我這里只是演示某種特殊的需求蠢熄。
好跪解,入正題;此時(shí)點(diǎn)擊獲取的是上一次值,我總不能把上一次的值傳給后臺掉接口吧叉讥。下面就給大家提供下解決方案窘行。

四 初始useCallback,以及大概使用图仓。

useCallback返回一個(gè) memoized 回調(diào)函數(shù)罐盔。
把內(nèi)聯(lián)回調(diào)函數(shù)及依賴項(xiàng)數(shù)組作為參數(shù)傳入 useCallback,它將返回該回調(diào)函數(shù)的 memoized 版本救崔,該回調(diào)函數(shù)僅在某個(gè)依賴項(xiàng)改變時(shí)才會更新惶看。當(dāng)你把回調(diào)函數(shù)傳遞給經(jīng)過優(yōu)化的并使用引用相等性去避免非必要渲染(例如 shouldComponentUpdate)的子組件時(shí),它將非常有用六孵。
更具體說明看官網(wǎng)介紹吧纬黎。
我這里就不多闡述了,直接講使用劫窒。

1. 新建 useSyncCallback.tsx
// useSyncCallback.tsx
import { useEffect, useState, useCallback } from "react";
const useSyncCallback = (callback: any) => {
    const [proxyState, setProxyState] = useState({ current: false });
    const [params, setParams] = useState([]);
    const Func = useCallback(
        (...args: []) => {
            setParams(args);
            setProxyState({ current: true });
        },
        [proxyState]
    );

    useEffect(() => {
        if (proxyState.current === true) setProxyState({ current: false });
    }, [proxyState]);

    useEffect(() => {
        proxyState.current && callback(...params);
    });

    return Func;
};
export default useSyncCallback;
2. 我的頁面引入本今,并使用它,替換掉原方法
import useSyncCallback from "./utils/useSyncCallback";

// 請求獲取數(shù)據(jù)
// const getListData = () => {
//     // 此時(shí)拿到的 code 其實(shí)是上一次的主巍。
//     console.log(cutTab) // 輸出的是上一次的冠息。
// };
const getListData = useSyncCallback(() => {
    console.log(cutTab) // 此時(shí)就是最新的值了
})

今天的干貨就講到這了,下一篇講講父子通訊孕索、兄弟通訊逛艰、以及useEffect(()=>{},[n])的基礎(chǔ)使用吧。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末檬果,一起剝皮案震驚了整個(gè)濱河市瓮孙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌选脊,老刑警劉巖杭抠,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異恳啥,居然都是意外死亡偏灿,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門钝的,熙熙樓的掌柜王于貴愁眉苦臉地迎上來翁垂,“玉大人,你說我怎么就攤上這事硝桩⊙夭拢” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵碗脊,是天一觀的道長啼肩。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么祈坠? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任害碾,我火速辦了婚禮,結(jié)果婚禮上赦拘,老公的妹妹穿的比我還像新娘慌随。我一直安慰自己,他們只是感情好躺同,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布阁猜。 她就那樣靜靜地躺著,像睡著了一般蹋艺。 火紅的嫁衣襯著肌膚如雪蹦漠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天车海,我揣著相機(jī)與錄音笛园,去河邊找鬼。 笑死侍芝,一個(gè)胖子當(dāng)著我的面吹牛研铆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播州叠,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼棵红,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了咧栗?” 一聲冷哼從身側(cè)響起逆甜,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎致板,沒想到半個(gè)月后交煞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡斟或,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年素征,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片萝挤。...
    茶點(diǎn)故事閱讀 39,690評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡御毅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出怜珍,到底是詐尸還是另有隱情端蛆,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布酥泛,位于F島的核電站今豆,受9級特大地震影響侈沪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜晚凿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望瘦馍。 院中可真熱鬧歼秽,春花似錦、人聲如沸情组。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽院崇。三九已至肆氓,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間底瓣,已是汗流浹背谢揪。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留捐凭,地道東北人拨扶。 一個(gè)月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像茁肠,于是被迫代替她去往敵國和親患民。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評論 2 353