每天对自己多问几个为什么,总是有着想象不到的收获。 一个菜鸟小白的成长之路(copyer)
1、异步useEffect(自定义hook)
// 定义
function useAsyncEffect(effect: () => Promise<void | (() => void)>, dependencies?: any[]) {
return useEffect(() => {
const cleanupPromise = effect()
return () => { cleanupPromise.then(cleanup => cleanup && cleanup()) } },
dependencies)
}
// 使用
useAsyncEffect(async () => {
const count = await fetchData() setCount(count) }, [fetchData])
2、useCallback的结合 useEffect使用
解决改变变量的时候,然后重新触发函数
// 定义变量
const [num, setNum] = useState(0)
// 一个函数依赖变量请求
const query = React.useCallback(() => {
console.log(num)
}, [num])
// 改变变量
const changeNum = () => {
setNum(2)
}
// 直接监听函数作为变量
React.useEffect(() => {
query()
}, [query])
query
函数,只要num发生变化,就会生产一个新的函数,就会重新触发 useEffect
3、函数组件的批量更新
// 实例1
const App = () => {
const [list, setList] = useState(null)
const [info, setInfo] = useState(null)
const btn = async () => {
setList([])
setInfo({})
}
React.useEffect(() => {
console.log(111);
})
return (
<div style={{padding: '40px'}}>
<Button onClick={btn}>点击</Button>
</div>
)
}
// 点击按钮的过程中,会触发两次render函数(初始化一次, 修改的state的批量跟新一次)
// 实例2
const App = () => {
const [list, setList] = useState(null)
const [info, setInfo] = useState(null)
const btn = async () => {
setTimeout(() => {
setList([])
setInfo({})
}, 0)
}
React.useEffect(() => {
console.log(111);
})
return (
<div style={{padding: '40px'}}>
<Button onClick={btn}>点击</Button>
</div>
)
}
//如果是异步的, 点击按钮的过程中,会触发三次render函数(初始化一次, 批量更新被破坏,两次修改state,就会触发两次)
所以在上面的过程中,如果是异步的,就会多触发一次,这里就有性能的浪费,那么该如何解决呢?
// 解决方式一 合并成一个对象(如果简单可以使用)
const [info, setInfo] = useState({list, [], info:{}})
// 解决方式二 使用react-dom中的 一个函数 手动批量更新
import { unstable_batchedUpdates } from 'react-dom'
setTimeout(() => {
unstable_batchedUpdates(() =>{
setList([])
setInfo({})
})
}, 0)
// 针对类组件也是一样的
4、ts书写自定义hooks
// 形式一
// 定义
import { useState, useCallback } from 'react'
interface Action<T> {
getData: () => T;
setData: (value: T) => void;
}
type IReturn<T> = [T, Action<T>]
function useData<T>(defaultValue: T): IReturn<T> {
const [state, setState] = useState<T>(defaultValue)
const actionData = useMemo(() => {
const getData = () => state
const setData = (value: T) => setState(value)
return {
getData,
setData
}
}, [])
return [state, actionData]
}
export default useData
// 使用
const [data1, setData1] = useData<string>(321)
// setData1是一个对象
// 方式二:
type IReturn<T> = [T, (value: T) => void]
function useData<T>(defaultValue: T): IReturn<T> {
const [state, setState] = useState<T>(defaultValue)
const actionData = useCallback((value: T) => {
setState(value)
}, [])
return [state, actionData]
}
export default useData
// 使用
const [data1, setData1] = useData<string>(321)
// setData1是一个函数