美文网首页
MobX in React 坑集

MobX in React 坑集

作者: fapiaopiao | 来源:发表于2019-07-08 18:00 被阅读0次

数据更新与生命周期

Bug: 父组件 setState 后,子组件未触发生命周期 willReceiveProps/Render,导致页面数据并没有更新。

分析

经反复测试发现,作为列表的父组件所拥有的前几个子组件是可以触发 render 的(will receive props 依然没有如期触发),处于后位的子组件则无法被触发。经此联想到父组件的 store 中也只存了前10个子组件所需的数据,后续子组件的数据走公共库中的 state,存在 observable 与 state 的分离。猜测是 MobX 的引入导致子组件的render方法是否触发只跟随 observable 变量,不再跟随 props 的改变。

于是抹去子组件的 inject/observer 装饰器,改为纯由 props 灌入数据。测试通过,will receive props/render 都正确地触发了。其中单纯抹去 observer,不抹去 inject 测试依然失败,表现与未调整时一致。

为什么 inject/observer会影响react的生命周期?读 MobX 源码可知,inject 方法实际上拦截了 props。

MobX  inject 方法源码

并在 observer 方法中重新去 observe 了render方法。

MobX observer 方法源码

源码注释中给了关于 Observer 实现的讲解视频,性感的咖喱味口音 https://www.youtube.com/watch?v=cPF4iBedoF0&feature=youtu.be&t=1307

这种做法相当于打断了React对于 props 的观察,使得跟 props 相关的生命周期无法正常工作。以下是一些坑友的经历和解释:

StackOverflow: The trick of using @observable is that it will trigger the update in the component without changing the props.

StackOverflow: Mobx doesn't update components by passing new props, it calls forceUpdate if any observable (not just props) accessed in render was modified.

结论

1. MobX observer 的使用打断了正常的 react props 更新流,使得只有当 observable 变量变化时,组件才会更新。

2. 而在我们的 Store 中,出于种种原因只存储了初始化数据时的前10个条目在数组里。后续增加的条目没有显式地用 action 去修改这个 observable 数组,只是单纯地 setState。所以 MobX 实际上并不认为这个 observable 数组在变化。这就是为什么处于列表前10个的条目可以触发 render,而超出10个的条目没有。

3. 但即使是前10的条目,也没有能触发 component will receive props 钩子。因为这个钩子只有在 props 变化的时候才会触发,这里的 props 是 store,而 store 是通过 context 传递的,必须是 final,所以永远也不会“变化”。

4. 在移除 observer 后,子组件的入参不再被 observer HOC 打断,能够正确地按照 react 的设计接收  props 的流动,各个生命周期也就得到了正确的触发。

5. 至于为什么移除 observer 保留 inject 仍然不能解决问题,因为在 MobX 的实现里,当 inject 的入参是一个函数时,默认 observe。

inject 函数源码,当入参是函数时,makeReactive 为 true

相关文章

网友评论

      本文标题:MobX in React 坑集

      本文链接:https://www.haomeiwen.com/subject/osddlttx.html