定义
自定义hook是一个函数,函数内部调用了其他hook
函数,且以use
开头命名,从而可称为自定义hook
其主要,是让代码拥有更好的重用性,依旧是函数式思维
基础使用
如计数器
import React, { useState } from "react"
export default function App() {
const [count, setCount] = useState(0)
return (
<div>
<p>当前数值:{count}</p>
<button onClick={() => setCount(count + 1)}>
增加
</button>
<button onClick={() => setCount(count - 1)}>
减少
</button>
</div>
)
}
将其改写成自定义hook形式,虽然对于计数器来说,可能有点哗众取宠
import React, { useState } from "react"
function useCount(initValue: number) {
const [count, setCount] = useState(initValue)
const add = () => setCount(count + 1)
const sub = () => setCount(count - 1)
return [count, add, sub] as [number, () => void, () => void]
}
export default function App() {
const [count, add, sub] = useCount(0)
return (
<div>
<p>当前数值:{count}</p>
<button onClick={add}>
增加
</button>
<button onClick={sub}>
减少
</button>
</div>
)
}
其优势可见于
- 复用性,可批量生产
- 修改权限封闭,对外界只提供两个访问函数
组合使用
如果将useState()
和useEffect()
组合起来使用会如何?
一个常见的场景,异步加载下拉框选项
import React, { useEffect, useState } from "react"
interface Option {
key: number
value: number
label: string
}
export default function App() {
const [options, setOptions] = useState<Option[]>([])
useEffect(() => {
setTimeout(() => {
setOptions([{ key: 1, value: 1, label: '1' }])
}, 100)
}, [])
return (
<div>
<select>
<option value={0}>--- 请选择 ---</option>
{options.map(item => <option {...item} />)}
</select>
</div>
)
}
存在多个下拉框时,其逻辑是一致的
const [options1, setOptions1] = useState<Option[]>([])
const [options2, setOptions2] = useState<Option[]>([])
const [options3, setOptions3] = useState<Option[]>([])
useEffect(() => {
setTimeout(() => {
setOptions1([{ key: 1, value: 1, label: '1' }])
setOptions2([{ key: 2, value: 2, label: '2' }])
setOptions3([{ key: 3, value: 3, label: '3' }])
}, 100)
}, [])
将其提取为自定义hook,大多数情况下,只需要暴露options
即可
function useOptions(url: string) {
const [options, setOptions] = useState<Option[]>([])
useEffect(() => {
axios.get<Option[]>(url).then(({ data }) => setOptions(data))
}, [])
return options
}
到了这一步,非常自然的,将其提取为一个组件
import React from "react"
import { useOptions } from "../hooks"
export default function Select({ url }: { url: string }) {
const options = useOptions(url)
return (
<select>
<option value={0}>--- 请选择 ---</option>
{options.map(item => <option {...item} />)}
</select>
)
}
而useOption()
还能单独使用,并没有粘合在其中,灵活性很高
小结
自定义hook主要特点
- 函数本能,多处重用
- 如同创建对象,只提供特定的数据与修改函数,封闭不必要的访问途径
- 自定义hook可继续嵌套组合,也是组件思想