useState
認(rèn)識(shí) useState
- useState 通過一個(gè)狀態(tài)變量來(lái)管理組件狀態(tài),在狀態(tài)發(fā)生變化時(shí)能夠自動(dòng)重新渲染組件
- useState 接收唯一一個(gè)參數(shù)椅寺,在組件第一次被調(diào)用時(shí)用來(lái)初始化值 痛黎。如果是個(gè)函數(shù)狸相,執(zhí)行函數(shù)并取返回值桩匪;如果不是函數(shù),直接賦值
- useState 的返回值是一個(gè)數(shù)組历筝,可以通過數(shù)組的解構(gòu)酗昼,方便調(diào)用
- useState 可以多次調(diào)用,每次調(diào)用 useState 都會(huì)創(chuàng)建一個(gè)新的 state 對(duì)象和對(duì)應(yīng)的 setState 函數(shù)梳猪,這樣能夠管理組件中多個(gè)狀態(tài)
使用方法
const [counter, setCounter] = useState(0)
const [name, setName] = useState(() => {
// 先執(zhí)行一定的邏輯麻削,后再返回初始值
const initialState = getFullName();
return initialState;
}); // 參數(shù)是 Function
useState 的實(shí)現(xiàn)原理
React 會(huì)將 state 對(duì)象和 setState 函數(shù)保存在“hook”對(duì)象中,每個(gè)組件都有自己獨(dú)立的 hook 對(duì)象春弥,用來(lái)存儲(chǔ)組件的狀態(tài)和更新函數(shù)呛哟。當(dāng)調(diào)用 useState()時(shí),會(huì)先檢查當(dāng)前組件是否已經(jīng)有對(duì)應(yīng)的 state匿沛,如果有就返回已有的 state扫责,否則就創(chuàng)建一個(gè)新的 state,并返回它
實(shí)現(xiàn)一個(gè)簡(jiǎn)單的 useState
function app() {
// const [num, setNum] = gyUseState(1);
const [num, setNum] = gyUseState(() => 100);
console.log(num);
return {
setNum,
};
}
// 全局對(duì)象fiber來(lái)保存上一次的狀態(tài)
let fiber = {};
// 區(qū)分是否調(diào)用過
let hasCalled = false;
function dispatch(pending, action) {
pending.action = action;
}
function gyUseState(initState) {
if (typeof initState === "function") {
initState = initState();
}
// 還沒有執(zhí)行過函數(shù)
if (!hasCalled) {
// 創(chuàng)建一個(gè)對(duì)象
const hook = {
basicState: initState,
pending: {
action: null,
},
};
// 掛載到fiber上
fiber.hook = hook;
// 標(biāo)記已經(jīng)執(zhí)行過
hasCalled = true;
return [hook.basicState, dispatch.bind(null, fiber.hook.pending)];
} else {
fiber.hook.basicState =
typeof fiber.hook.pending.action === "function"
? fiber.hook.pending.action(fiber.hook.basicState)
: fiber.hook.pending.action;
// 返回?cái)?shù)組
return [fiber.hook.basicState, dispatch.bind(null, fiber.hook.pending)];
}
}
const myApp = app(); // 100
// myApp.setNum(10)
// app()
myApp.setNum((num) => num + 1);
app(); // 101