React中通过setState规避stale state及支持异步的方案是否可行?
关于React中一种useState替代方案的可行性疑问
我未找到类似实现,因此想了解该方案在React中是否可行?
useState存在的问题
- 易出现stale value(触发场景并不明显),比如部分场景下状态变量处于stale状态,会导致计算结果异常。
- 无法在状态更新逻辑中便捷使用异步函数。
提出的解决方案
该方案仅使用setState函数实现:
// Mutex class Mutex { // 实现细节省略,可通过实例维护Promise对象,在unlock中resolve来实现 lock = async () => {...}; unlock = () => {...}; } // 组件示例 const MyComponent = () => { const [counter, setCounter] = useState(0); const mutex = useRef(new Mutex()); const handler = useCallback(async () => { await mutex.lock(); let curCounter = await new Promise((res, rej) => { // 利用setCounter作为"探针"获取当前counter值 setCounter((v) => { res(v); return v; }); }); // 支持异步操作 curCounter += await getDelta(); setCounter(curCounter); mutex.unlock(); }, []); // 依赖列表为空,无需直接依赖counter return (<Button onClick={handler}>Click</Button>); }
该方案看似刻意,但逻辑可抽象为以setState为入参的可复用高阶函数。它同时解决了stale变量问题(不直接依赖状态变量)并支持异步函数。
方案注意事项
- 必须使用Mutex防止并发调用,否则
curCounter可能出现竞态条件,这会带来性能损耗。 - 可能需要处理可重入锁的场景。
- 必须记得调用解锁操作,否则程序会挂起。
更新说明
感谢各位的回复。
异步支持实际上是核心问题,stale state相对容易修复。
内容的提问来源于stack exchange,提问作者stackoverflower
相关产品推荐
相关产品推荐

