响应式hooks-useReactive

143 阅读1分钟

因为Vue是数据响应式的,咱们React没有,但是咱们可以自己实现呀

需求

我们先捋清楚需要实现什么

  • 监听数据变化(get、set)
  • 数据变化的时候,更新页面

监听数据

从Vue3中很容易知道,通过Proxy可以实现数据响应式监听

const data = {};
new Proxy(data, {
    get: (target, key) => { // 获取值
       return Reflect.get(target, key)
    },
    set: (target, key, value) => { // 设置值
        return Reflect.set(target, key, value)
    }
})

主动更新

这是一个老生常谈的问题:hooks如何模拟class组件的this.forceUpdate函数

const useUpdate = () => {
    const [_, setState] = useState({});
    const forceUpdate = () => setState({});
    return [forceUpdate]
}

实现

好了,基于以上,可以实现useReactive

import { useState, useRef } from "react"

const useReactive = <T extends Record<string, any>> = (initialState: T) => {
    const ref = useRef(initialState);
    const [forceUpdate] = useUpdate();
    const proxyRef = useRef(new Proxy(ref.current, {
        get: (target: T, key: string | symbol) => { // 获取值
           return Reflect.get(target, key)
        },
        set: (target: T, key: string, value: any) => { // 设置值
            const ret = Reflect.set(target, key, value)
            forceUpdate();
            return ret;
        }
    }));
    return proxyRef.current;
}

到此为止,已经实现了最基本的用法,当然还有更多的情况,比如响应式的是一个常量,当修改这个常量的时候,如何实现响应。

这里当然只提供了基本的用法和思路

使用


const App = () => {
    const data = useReactive({ count: 0 });
    return <Button onClick={() => data.count++}>点击我{data.count}<Button>
}

传送门