由于一直感觉hook不颗粒化用起来真的很难受 useState多了可读性就极差 于是自己尝试去造一个和class组件this.setState功能一样的useState
防止被喷 最终结果是 失败了
this.setState的用法
- 最常用
this.setState({ data })
- 函数式
// 可拿到修改前的state
this.setState(prev => ({ visible: !prev.visible }))
- 回调
this.setState({ data }, () => {
// 可拿到修改后的
console.log(this.state.data)
})
自定义hook的基础用法
// 自定义组件
import { useState } from "react"
const useSelfuseState = (initialState) => {
const [state, setState] = useState(initialState)
const selfSet = (_state) => {
// todo 这里我们可以自己随便处理传入的想要修改的state
setState(_state)
}
return [state, selfSet]
}
export default useSelfuseState
最终
// 自定义的useState
import { useState, useRef, useEffect } from "react"
import { selfTypeof } from '@/utils/tools'
export default function usePublicStateChange<S>(initialState: S): [state: S, selfSetState: <K extends keyof S>(state: ((prev: S) => Pick<S, K>) | Pick<S, K>, callback?: (state: S) => void) => void] {
const selfCallback = useRef<Function | undefined>(void 0)
const [state, setState] = useState<S>(initialState)
useEffect(() => {
if (selfTypeof(selfCallback.current, "function")) {
(selfCallback.current as Function)(state)
selfCallback.current = void 0
}
}, [state])
const selfSetState: <K extends keyof S>(_state: Pick<S, K> | ((prev: S) => Pick<S, K>), callback?: (state: S) => void) => void = (_state, callback) => {
callback && (selfCallback.current = callback)
selfTypeof(_state, 'function') ? setState((prev: S): S => ({ ...prev, ...(_state as Function)(prev) })) : setState((prev: S): S => ({ ...prev, ..._state }))
}
return [state, selfSetState]
}
因项目里有ts 所以默认用了 这里就不去掉了 用的不好 勿喷
- 这边我验证了传入的第一个参数是否是函数 是的话则调用这个函数处理即可
- 如果是直接传入要修改的数据 直接修改即可 不过useState的用法都需要合并prevState
- 最后就是关于这个回调函数 我尝试将他存在了ref里 因为ref是完全同步的
- 根据当前的state发生变化 然后再去调用这个回调函数
- 最终的结果是 在上一层组件中 回调函数作用域里的state还是上一次的 虽然当前自定义组件中确实已经更新了 但是更新的内容并没有更新到上一层组件里 至少在调用的时候还没有 所以我失败了
- 最后只能倔强的传最新的state过去 但这样是有很大弊端的 有些功能勉强能用 但无法实现和this.setState一模一样的效果