记录Recoil的一个问题

198 阅读2分钟

写在前面:前端小白一名,最近在做一个项目,使用了React+Recoil+Graphology。本文先用来记录一下发生的问题,后续补齐Recoil相关源码的解读。

背景

Graphology是一个js实现的图数据结构库,其中提供了一个Graph类,维护了一个nodes数组,一个edges数组,还有一些操作图中节点和边的方法。Graph类继承了一个Event类,Event类有一个on方法,可以对事件绑定回调函数;有一个_eventCount属性,number,当绑定一个事件的时候++。

过程

用户通过输入一些参数,生成一个Graph对象,对象很庞大,所以在用户没有新的输入时,尽量不更新Graph对象。

很多组件都需要用到这个对象,于是存储在recoil中。

问题发生了,当我注册事件的时候,老是报错,大意就是无法赋值给只读属性_eventCount。

Debug了一中午,结合了源码,得到的分析结果是:recoil在set的时候,对传入对象进行了深拷贝,并将对象的属性和原型链上所有的属性设置成了只读,防止用户手动更改属性,而只能通过recoil的接口,整个替换掉存储的对象。

总结

Recoil中的状态如果是一个对象,那么对象所有的属性都是只读的。

个人认为,这个出发点应该是好的,但是在使用过程中造成了巨大的困惑,且没有在官方文档中指出。在context或者state中直接修改对象的属性,是可行的,但是不会触发更新。而有的业务场景下,我们需要直接修改state对象中的属性,且我们不需要修改后触发更新,例如给Graph对象绑定事件这个操作,对程序员来说是透明的,对象自己维持了_eventCount属性,而且并不需要更新整个recoil中的对象。这样一来recoil反而有了个弊端。 另外,第三方库在开发过程中也不会考虑这个问题,导致第三方库直接没法在recoil中用。