因为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>
}