Scenes
When you see the title, you might think: Why do you do this?
React hooks are a useful invention that reorganizes the pattern of writing and thinking about code, using smaller abstractions to separate state and functions by function, rather than lumping them into a single state or lifecycle. But react hooks have the concept of state dependence, and what's worse: it relies on manual management -- although react officially provides eslint rules, if you have used it, you will find that it has a high false positive rate -- especially in in complex components.
So, does this mean there is no solution? No, the author of vue3 talked about the improvement of vue3 hooks compared to react hooks in a speech, one of which is that there is no need to manually manage dependencies, you can watch dotJS 2019 - Evan You - State of Components. But react is better ecologically (including various libraries and IDE development experience), so I try to implement automatic dependency management in react in some way, and implement some primitive hooks that behave like vue3.
The main sources of inspiration for this are solid.js and react-easy-state.
think
List of common primitive hooks for vue3
- ref
- reactive
- computed
- watchEffect
- watch
When it comes to mutable state in react, the easiest thing to think of is mobx (as opposed to immutable redux), so the following will implement the above based on it hooks function.
accomplish
import { observer } from 'mobx-react'
import { action, autorun, computed, observable, reaction } from 'mobx'
import { useCallback, useEffect, useMemo, useState } from 'react'
export function useVReactive<T extends object>(value: T): T {
const[state] = useState(() => observable(value))
return state
}
export function useVRef<T>(value: T): { value: T } {
return useVReactive({ value })
}
export function useVComputed<T>(fn: () => T): { value: T } {
const computedValue = useMemo(() => computed(fn), [])
return {
get value() {
return computedValue.get()
},
}
}
export function useVFn<T extends (...args: any[]) => any>(fn: T): T {
return useCallback(action(fn), [])
}
export function useVWatch(deps: () => any, fn: () => void): void {
useEffect(() => reaction(deps, fn), [])
}
export function useVWatchEffect(fn: () => void): void {
useEffect(() => autorun(fn), [])
}
const contextMap = observable(new Map<ContextKey<any>, any>())
// eslint-disable-next-line
export interface ContextKey<T> extends Symbol {}
export function useVProvide<T>(key: ContextKey<T>, value: T): void {
useState(action(() => contextMap.set(key, value)))
useEffect(
action(() => {
contextMap.set(key, value)
return action(() => {
contextMap.delete(key)
})
}),
[],
)
}
export function useVInject<T>(key: ContextKey<T>): T | undefined {
const value = useMemo(() => computed(() => contextMap.get(key)), [])
const state = useVRef(value.get())
useVWatchEffect(() => (state.value = value.get()))
return state.value
}
export const defineComponent = observer
We have published it to npm @liuli-util/mobx-vue3-hooks
use
It feels similar to vue3 hooks to use, just declare a state, then modify it directly, and everything will respond automatically - no need to manually manage dependencies and understand the mental model of hooks.
import {
defineComponent,
useVRef,
useVFn,
useVComputed,
} from '@liuli-util/mobx-vue3-hooks'
const HelloWorld = defineComponent(() => {
const state = useVRef(0)
const computedValue = useVComputed(() => state.value * 2)
const onInc = useVFn(() => {
state.value++
})
return (
<div>
<button onClick={onInc}>Add</button>
<div>{computedValue.value}</div>
</div>
)
})
Due to some reasons, we have not fully realized the effect of vue3 hooks, such as
- You need to use
useVFn
to wrap the function of the operation state, but in vue3, you only need to declare a normal function in the setup function. -
useWatch
uses computed functions, while vue3 uses dependent state arrays - Must use
defineComponent
to wrap the component, in vue3 it is just a code hint
Summarize
The react ecology does have all kinds of things, and the ecology is super rich, but some details are relatively rough, especially when the official let it go. My generation used to have this question: Why is no one feeling weird about what is happening now? For example, react-router v4=>v6 blind update, material-ui/fluentui form and table components are almost unavailable compared to antd, redux complexity is still necessary as the default state manager, react hooks dependency management depends on Labor is very annoying, why do dozens of css in js schemes not be managed by the official government and so on.
Top comments (0)