自定义useState

938 阅读2分钟

由于一直感觉hook不颗粒化用起来真的很难受 useState多了可读性就极差 于是自己尝试去造一个和class组件this.setState功能一样的useState

防止被喷 最终结果是 失败了

this.setState的用法

  1. 最常用
this.setState({ data })
  1. 函数式
// 可拿到修改前的state
this.setState(prev => ({ visible: !prev.visible }))
  1. 回调
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 所以默认用了 这里就不去掉了 用的不好 勿喷

  1. 这边我验证了传入的第一个参数是否是函数 是的话则调用这个函数处理即可
  2. 如果是直接传入要修改的数据 直接修改即可 不过useState的用法都需要合并prevState
  • 最后就是关于这个回调函数 我尝试将他存在了ref里 因为ref是完全同步的
  • 根据当前的state发生变化 然后再去调用这个回调函数
  • 最终的结果是 在上一层组件中 回调函数作用域里的state还是上一次的 虽然当前自定义组件中确实已经更新了 但是更新的内容并没有更新到上一层组件里 至少在调用的时候还没有 所以我失败了
  • 最后只能倔强的传最新的state过去 但这样是有很大弊端的 有些功能勉强能用 但无法实现和this.setState一模一样的效果