共计 3256 个字符,预计需要花费 9 分钟才能阅读完成。
useToggle
剖析的源码来自:https://github.com/alibaba/ho…
首先,useToggle 用于在两个状态值间切换的 Hook。默认为 boolean 类型,但不仅仅是 boolean,也可依据具体情况传入须要的两个状态,并进行切换;同样性能虽利用 useState 也可实现,但不如从新实现一个 hook 来得便当。
根本用法
三个重载
- 第一个重载为 boolean 之间切换,初始状态默认为 false。此时 defaultValue 为初始状态(true 或 false),reverseValue 为另一个值。
- 第二个重载传入一个参数 defaultValue,此时 reverseValue 为!defaultValue。
- 第三个重载传入两个参数,defaultValue 和 reverseValue。
四个办法
- setLeft:state 批改为 defaultValue。
- setRight:state 批改为 reverseValue。
- toggle:状态在 defaultValue 和 reverseValue 中切换。
- set:带参数,切换为 defaultValue 或者 reverseValue。
应用示例
export default () => {const [state, { toggle, set, setLeft, setRight}] = useToggle('yes', 'no'); | |
return ( | |
<div> | |
<p>{state}</p> | |
<p> | |
<button type="button" onClick={toggle}> | |
Toggle | |
</button> | |
<button type="button" onClick={() => set('yes')} style={{margin: '0 8px'}}> | |
Set yes | |
</button> | |
<button type="button" onClick={() => set('no')}> | |
Set no | |
</button> | |
<button type="button" onClick={setLeft} style={{margin: '0 8px'}}> | |
Set Left | |
</button> | |
<button type="button" onClick={setRight}> | |
Set Right | |
</button> | |
</p> | |
</div> | |
); | |
}; |
源码剖析
import {useMemo, useState} from 'react'; | |
// 定义了动作接口,内含四个办法 | |
export interface Actions<T> {setLeft: () => void; | |
setRight: () => void; | |
set: (value: T) => void; | |
toggle: () => void;} | |
// 进行三次函数重载 | |
function useToggle<T = boolean>(): [boolean, Actions<T>]; | |
function useToggle<T>(defaultValue: T): [T, Actions<T>]; | |
function useToggle<T, U>(defaultValue: T, reverseValue: U): [T | U, Actions<T | U>]; | |
function useToggle<D, R>(defaultValue: D = false as unknown as D, reverseValue?: R) { | |
// 外部应用 useState 创立了根本的 state,类型为联结类型 D | R,// 也就是传入的两种状态:defaultValue 和 reverseValue(如果有)的类型 | |
const [state, setState] = useState<D | R>(defaultValue); | |
// 用 useMemo 包装,返回四个办法 | |
const actions = useMemo(() => { | |
// 定义 reverseValueOrigin,为 reverseValue 或!defaultValue(依据 reverseValue 是否存在)const reverseValueOrigin = (reverseValue === undefined ? !defaultValue : reverseValue) as D | R; | |
const toggle = () => setState((s) => (s === defaultValue ? reverseValueOrigin : defaultValue)); | |
const set = (value: D | R) => setState(value); | |
const setLeft = () => setState(defaultValue); | |
const setRight = () => setState(reverseValueOrigin); | |
return { | |
toggle, | |
set, | |
setLeft, | |
setRight, | |
}; | |
// useToggle ignore value change | |
// }, [defaultValue, reverseValue]); | |
}, []); | |
return [state, actions]; | |
} | |
export default useToggle; |
源码的外部逻辑较为简单:
- 首先定义了动作接口,蕴含该 hook 的四个扭转状态的办法。
- 外部应用了 useState 创立了根本的 state,类型为联结类型(即传入的两个初始值的类型)。
- 应用 useMemo 定义四个扭转状态的办法并 return。
- 值得注意的是在封装办法的时候应用了 useMemo。
要点阐明:useMemo 的应用
useMemo 的作用跟 useCallback 类似,只是用法有所不同。useMemo 的计算结果是回调函数中 return 的值,在 useToggle 源码中为四个办法
该 hook 返回一个 memoized 值,仅在第二项参数数组中的某一依赖项产生扭转时才会从新计算;而在上述应用场景中,依赖项为空数组,那么就在初始的时候只执行一次,当组件从新渲染时不会再执行,有助于缩小耗费。
参考资料:
https://react.docschina.org/d…
useBoolean
该 hook 用于治理 boolean 状态。能够看出 useBoolean 与 useToggle 很类似,只是适用范围更加狭隘;实际上 useBoolean 的确是应用 useToggle 封装,这也是本文将二者放在一起探讨的起因。
根本用法
四个办法
- setTrue:state 批改为 true。
- setFalse:state 批改为 false。
- toggle:状态在 true 和 false 中切换。
- set:带参数,将状态设置为 true 或 false。
-
应用示例
const [state, { toggle, setTrue, setFalse}] = useBoolean(true);
源码剖析
该源码较为简单,外部间接应用了 useToggle 进行封装。
import {useMemo} from 'react'; | |
import useToggle from '../useToggle'; | |
// 规定了 Actions 接口,蕴含四个办法 | |
export interface Actions {setTrue: () => void; | |
setFalse: () => void; | |
set: (value: boolean) => void; | |
toggle: () => void;} | |
export default function useBoolean(defaultValue = false): [boolean, Actions] { | |
// 应用 useToggle 进行封装,并间接用了它的 toggle, set 办法 | |
const [state, { toggle, set}] = useToggle(defaultValue); | |
// 用 useMemo 包装,返回四个办法 | |
const actions: Actions = useMemo(() => {const setTrue = () => set(true); | |
const setFalse = () => set(false); | |
return { | |
toggle, | |
set: (v) => set(!!v), | |
setTrue, | |
setFalse, | |
}; | |
}, []); | |
return [state, actions]; | |
} |
正文完
发表至: typescript
2022-11-19