实现 useCounter
hook 的优化版本。返回的方法应该被记忆化,在重新渲染时返回相同的函数实例。
export default function Component() {const { count, increment, decrement, reset, setCount } = useCounter();return (<div><p>Counter: {count}</p><button onClick={increment}>Increment</button><button onClick={decrement}>Decrement</button><button onClick={reset}>Reset</button></div>);}
initialValue: number
: 计数器状态的初始值。如果未提供,则应默认为 0
。useCounter
hook 返回一个具有以下属性的 object
:
count: number
: 当前计数器值increment: () => void
: 增加计数器值的函数decrement: () => void
: 减少计数器值的函数reset: () => void
: 将计数器值重置为 initialValue
的函数,如果未提供则为 0
setCount: (value: number) => void
: 将计数器值设置为 value
的函数,它与 setState
具有相同的签名increment
、decrement
、reset
和 setCount
在重新渲染时必须是相同的函数实例。
实现 useCounter
hook 的优化版本。返回的方法应该被记忆化,在重新渲染时返回相同的函数实例。
export default function Component() {const { count, increment, decrement, reset, setCount } = useCounter();return (<div><p>Counter: {count}</p><button onClick={increment}>Increment</button><button onClick={decrement}>Decrement</button><button onClick={reset}>Reset</button></div>);}
initialValue: number
: 计数器状态的初始值。如果未提供,则应默认为 0
。useCounter
hook 返回一个具有以下属性的 object
:
count: number
: 当前计数器值increment: () => void
: 增加计数器值的函数decrement: () => void
: 减少计数器值的函数reset: () => void
: 将计数器值重置为 initialValue
的函数,如果未提供则为 0
setCount: (value: number) => void
: 将计数器值设置为 value
的函数,它与 setState
具有相同的签名increment
、decrement
、reset
和 setCount
在重新渲染时必须是相同的函数实例。
useCounter
钩子使用 useState
来管理 number
状态。 setter 函数可以根据 useState
钩子的 setValue
来实现。
import { useState } from 'react';export default function useCounter(initialValue = 0) {const [count, setCount] = useState(initialValue);return {count,increment: () => setCount((x) => x + 1),decrement: () => setCount((x) => x - 1),reset: () => setCount(initialValue),setCount,};}
但是,这样编写钩子意味着依赖于实用函数的组件将始终被重新渲染,因为这些函数总是在每次渲染时被重新创建。 为了避免这种情况,我们可以使用 useCallback
来记忆它们。
import { Dispatch, SetStateAction, useCallback, useState } from 'react';interface UseCounterReturn {count: number;increment: () => void;decrement: () => void;reset: () => void;setCount: Dispatch<SetStateAction<number>>;}export default function useCounter(initialValue = 0): UseCounterReturn {const [count, setCount] = useState(initialValue);const increment = useCallback(() => {setCount((x) => x + 1);}, []);const decrement = useCallback(() => {setCount((x) => x - 1);}, []);const reset = useCallback(() => {setCount(initialValue);}, [initialValue]);return {count,increment,decrement,reset,setCount,};}
为了确保一致性,increment
和 decrement
函数使用 更新器函数 来根据先前的值计算新值。 另外,如果您将它们包装在 useCallback
中,则不必将 initialValue
添加到依赖项数组中,并且 increment
和 decrement
将始终被记忆一次。
如果您使用 TypeScript,棘手的部分是确定 setCount
的正确类型,因为它也可以接受更新器函数。 只需将您最喜欢的 IDE 中的 setter 函数从 useState
悬停,您将看到类型签名,形式为 Dispatch<SetStateAction<...>>
,其中状态的类型为 ...
。 Dispatch
和 SetStateAction
可以从 react
导入。
如果您更喜欢冗长,它本质上可以归结为这样。
type SetCount = (valueOrUpdater: number | ((previousValue: number) => number),) => void;
console.log()
语句将显示在此处。