React.useState替代方案:对象式useState的实现及问题咨询
objectUseState数组操作兼容优化方案
你当前实现的核心问题是只对顶层对象的属性赋值做了拦截,没有递归处理嵌套的引用类型(比如数组、子对象),所以数组的push等变异操作无法被拦截触发更新,可通过以下思路优化:
- 递归代理所有嵌套引用类型:在Proxy的get拦截逻辑中增加判断,只要获取到的属性值是对象/数组类型,就给它也套上一层相同的Proxy再返回,保证嵌套层级的所有修改操作都能被拦截到。
- 适配数组变异方法:数组的push、pop、splice等变异方法本质最终都会触发数组元素或length属性的set操作,只要你完成了数组的Proxy包装,这些操作天然就能被拦截到触发更新;如果存在特殊场景漏触发的情况,可以专门在get拦截中对数组的变异方法做包装,执行完原方法后手动触发一次状态更新即可。
- 集成Immer简化不可变更新:你可以直接在状态更新逻辑中引入Immer的produce方法,不需要自己手动处理深拷贝逻辑,所有对代理对象的修改都会被Immer转化为符合React要求的不可变状态更新,天然支持数组的所有操作,还能保证未修改属性的引用稳定,避免useEffect等依赖项的意外触发。
以下是精简实现示例:
import { produce } from 'immer'; import { useState, useMemo } from 'react'; function objectUseState(initialState) { const [state, setState] = useState(initialState); const proxy = useMemo(() => { const createProxy = (target) => { return new Proxy(target, { set(obj, prop, value) { setState(prev => produce(prev, draft => { draft[prop] = value; })); return true; }, get(obj, prop) { const value = obj[prop]; // 嵌套对象/数组继续做代理包装 if (typeof value === 'object' && value !== null) { return createProxy(value); } return value; } }); }; return createProxy(state); }, [state]); return proxy; }
使用该实现后,数组的push等操作可正常触发更新,示例如下:
const state = objectUseState({ list: [] }); // 点击后会往list新增元素并触发视图更新 return <Text onPress={() => state.list.push('新元素')}>{state.list.length}</Text>
内容的提问来源于stack exchange,提问作者Alen.Toma
相关产品推荐
相关产品推荐

