资讯专栏INFORMATION COLUMN

React Native 搭配 MobX 使用心得

MSchumi / 2093人阅读

摘要:通过可以让识别列表长度变化自动更新列表,利用维护项数据可以使每个项保持响应式却互不影响,对长列表优化效果很明显。最好的方式是将数据统一放在中,子组件通过方式获取数据。

MobX 是一款十分优秀的状态管理库,不但书写简洁还非常高效。当然这是我在使用之后才体会到的,当初试水上车的主要原因是响应式,考虑到可能会更符合 Vue 过来的思考方式。然而其实两者除了响应式以外并没有什么相似之处。

在使用过程中走了不少弯路,一部分是因为当时扫两眼文档就动手,对 MobX 机制理解得不够;其它原因是 MobX 终究只是一个库,会受限于 React 机制,以及与其它非 MobX 管理组件的兼容问题。当中很多情况在文档已经给出了说明(这里和这里),我根据自己遇到的再做一番总结。

与非响应式组件兼容问题

与非响应式的组件一起工作时,MobX 有时需要为它们提供一份非响应式的数据副本,以免 observable 被其它组件修改。

observable.ref

使用 React Navigation 导航时,如果要交由 MobX 管理,则需要手动配置导航状态栈,此时用 @observable.ref “浅观察”可避免状态被 React Navigation 修改时触发 MobX 警告。

当 Navigator 接受 navigation props 时代表导航状态为手动管理。

import { addNavigationHelpers, StackNavigator } from "react-navigation"
import { observable, action } from "mobx"
import { Provider, observer } from "mobx-react"
import AppComp from "./AppComp"

const AppNavigator = StackNavigator({
  App: { screen: AppComp },
  // ...
}, {
  initialRouteName: "App",
  headerMode: "none"
})

@observer
export default class AppNavigation extends Component {
  @observable.ref navigationState = {
    index: 0,
    routes: [
      { key: "App", routeName: "App" }
    ],
  }

  @action.bound dispatchNavigation = (action, stackNavState = true) => {
    const previousNavState = stackNavState ? this.navigationState : null
    this.navigationState = this.AppNavigator.router.getStateForAction(action, previousNavState)
    return this.navigationState
  }

  render () {
    return (
      
        
      
    )
  }
}
observable.shallowArray()observable.shallowMap()

MobX 还提供其它方便的数据结构来存放非响应式数据。

比如使用 SectionList 的时候,我们要为其提供数据用于生成列表,由于 Native 官方的实现跟 MobX 不兼容,这个数据不能是响应式的,不然 MobX 会报一堆警告。

MobX 有个 mobx.toJS() 方法可以导出非响应式副本;如果结构不相同还可以使用 @computed 自动生成符合的数据。但这两个方法每次添加项目都要全部遍历一遍,可能会存在性能问题。

这时其实可以维护一个 observable.shallowArray,里面只放 key 数据,只用于生成列表(像骨架一样)。传给 SectionListsections props 时 slice 数组复制副本(shallowArray 里的数据非响应式,所以只需浅复制,复杂度远小于上面两种方式)。

然后 store 维护一个 observable.map 来存放每个项的数据,在项(item)组件中 inject store 进去,再利用 key 从 map 中获取数据来填充。

通过 shallowArray 可以让 MobX 识别列表长度变化自动更新列表,利用 map 维护项数据可以使每个项保持响应式却互不影响,对长列表优化效果很明显。

// store comp
class MyStore {
  @observable sections = observable.shallowArray()
  @observable itemData = observable.map()

  @action.bound appendSection (section) {
    const data = []
    section.items.forEach(action(item => {
      this.itemData.set(item.id, item)
      data.push({key: item.id})
    }))
    this.sections.push({
      key: section.id,
      data
    })
  }
}
// MyList comp
import { SectionList } from "react-native"
@inject("myStore")
@observer
class MyList extends React.Component {
  _renderItem = ({item}) => 

  render () {
    return (
      
    )
  }
}
// SectionItem comp
@inject("myStore")
@observer
class SectionItem extends React.Component {
  render () {
    const {myStore, id} = this.props
    const itemData = myStore.itemData.get(id)
    return (
      {itemData.title}
    )
  }
}
computed

利用 @computed 缓存数据可以做一些优化。

比如有一个响应式的数组 arr,一个组件要根据 arr 是否为空更新。如果直接访问 arr.length,那么只要数组长度发生变化,这个组件都要 render 一遍。

此时利用 computed 生成,组件只需要判断 isArrEmpty 就可以减少不必要的更新:

@computed get isArrEmpty () {
  return this.arr.length <= 0
}
observable.map

因 JS 机制 MobX 不能检测属性的增删,所以最好用 observable.map 取代简单 {} 对象。另外 MobX 没有提供 Set 支持,可以用 key 和 value 一样的 Map 代替。

避免在父组件中访问子组件的属性

这条规则在文档也提到,原因很简单,MobX 对于一个 observer 组件,是通过访问属性来记录依赖的。所以哪怕父组件里没有用到这个属性,只是为了作为 props 传给子组件,MobX 还是算它依赖了这个属性,于是会产生不必要的更新。最好的方式是将数据统一放在 store 中,子组件通过 inject store 方式获取数据。

小组件

由于 React 的机制,MobX 只能在组件层面发光发热,对于组件内部就无能为力了。所以大组件用 MobX 很容易卡死(用其它也会),小组件才能真正发挥 MobX 自动管理更新的优势。

博客链接:https://blog.crimx.com/2017/1...

【完】

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/89757.html

相关文章

  • 前端每周清单第 45 期: Safari 支持 Service Worker, Parcel 完整教

    摘要:的另一个核心特性,苹果表示也正在开发中,按开发进度可能几个月后就能与我们见面。是基于的本地化数据库,支持以及浏览器环境。 前端每周清单专注前端领域内容,以对外文资料的搜集为主,帮助开发者了解一周前端热点;分为新闻热点、开发教程、工程实践、深度阅读、开源项目、巅峰人生等栏目。欢迎关注【前端之巅】微信公众号(ID: frontshow),及时获取前端每周清单。 本期是 2017 年的最后一...

    赵春朋 评论0 收藏0
  • Mobx + React Native 获取路由的状态信息

    摘要:年前公司由一个项目是使用来开发的所以遇到了一些问题比较影响开发进程的就是路由问题了实际上就是这个组件比较难懂这里给大家讲解一下希望大家少踩点坑另外本篇文章使用的是环境主要讲解的还是如何使用记录中路由的状态但是会穿插一些小内容这里虽然讲到的是 年前公司由一个项目是使用 ReactNative 来开发的所以遇到了一些问题,比较影响开发进程的就是路由问题了,实际上就是 ReactNaviga...

    李涛 评论0 收藏0
  • MobX学习之旅

    摘要:一其实是一个比较轻便的可扩展的状态管理工具,是一个由以及一些其他团队的人共同维护的开源项目。当应用公共状态的组件在状态发生变化的时候,会自动完成与状态相关的所有事情,例如自动更新自动缓存数据,自动通知等。 一、MobX MobX其实是一个比较轻便的可扩展的状态管理工具,是一个由Facebook以及一些其他团队的人共同维护的开源项目。 当应用公共状态的组件在状态发生变化的时候,会自动完...

    刘福 评论0 收藏0
  • 我为什么从Redux迁移到了Mobx

    摘要:需要注意的是,在中,需要把数据声明为。同时还提供了运行时的类型安全检查。在利用了,使异步操作可以在一个函数内完成并且可以被追踪。例如在中,数组并不是一个,而是一个类的对象,这是为了能监听到数据下标的赋值。 Redux是一个数据管理层,被广泛用于管理复杂应用的数据。但是实际使用中,Redux的表现差强人意,可以说是不好用。而同时,社区也出现了一些数据管理的方案,Mobx就是其中之一。 R...

    DevYK 评论0 收藏0
  • Redux 的问题:ReactMobX 和 Realm 能解决吗?

    摘要:它是由一个非常聪明的人开发的,用来缓解在单页面应用中管理状态的问题。的问题没有一种适合所有场景的完美工具。为设计的是世界的另一个新增内容,但目前仅适用于。这将导致最后期限延长,并且留下更多需要我们维护的代码。 原文:The Problems with Redux: Can React, MobX, and Realm save us? 作者:Erich Reich 首先,我不讨厌 ...

    snifes 评论0 收藏0

发表评论

0条评论

MSchumi

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<