Skip to main content
Version: 6.x

与 MobX 状态树集成

注意

本指南不完整。请通过发送拉取请求来帮助改进这一点。

¥This guide is incomplete. Please help improve this by sending pull requests.

本指南探讨了在使用 MobX 状态树(MST) 进行状态管理的 React Native 项目中使用 React Navigation 的可能方法。该指南附有 示例应用。本指南的部分内容可能也与 MobX 的用户相关,但请注意 MobX 没有提供用于(反)序列化其状态的内置解决方案。

¥This guide explores possible way to use React Navigation in a React Native project that uses MobX State Tree(MST) for state management. The guide is accompanied by a sample app. Parts of the guide may be relevant also for users of MobX but please be aware of the fact that MobX does not come with a built-in solution for (de)serializing its state.

注意

请注意,在本指南中,Mobx State Tree 不用于管理导航状态本身 - 只是导航参数!

¥Please note that in this guide, Mobx State Tree is not used to manage the navigation state itself - just the navigation params!

概述

¥Overview

我们本指南的目标是将 MST 与 React Navigation 结合使用并实现最佳的开发者体验。在本指南的范围内,这意味着允许我们执行完整的 JS 重新加载并返回到重新加载发生之前的状态。

¥Our goal with this guide is to use MST with React Navigation and achieve optimal developer experience. In the scope of this guide, this means allowing us to do a full JS reload and be brought back to the state before the reload happened.

我们将通过使用 React Navigation 的 内置机制 持久化 导航状态 来实现这一点。我们还需要保留应用状态和导航参数 - 这样,当你在应用的屏幕上工作并执行完整的 JS 重新加载时,你将返回到同一屏幕,其中包含相同的数据。

¥We will do this by persisting the navigation state using the React Navigation's built-in mechanism. We also need to persist the app state and navigation params - that way, when you're working on a screen in your app and do a full JS reload, you will be brought back to the same screen, with the same data in it.

指南

¥Guide

首先,从创建初始导航结构和 React 组件开始。完成后,继续在 MST 中对你的状态进行建模。如果你想了解更多信息,请查看 Egghead.io 课程

¥First, start by creating initial navigation structure and React components. When you're done with that, continue with modelling your state in MST. If you want to learn more about this, check out the egghead.io course.

此时,你可能想知道如何将 MST 对象与组件连接起来。答案就在 mobx-react 包 中,其中包含 MobX 的 React 绑定(它们也适用于 MST)。你可能会使用 Provider 组件以及 injectobserver 函数。

¥At this point, you're probably wondering how to connect your MST objects with the components. The answer is in the mobx-react package that contains React bindings for MobX (they also work for MST). You will likely be using the Provider component and the inject and observer functions.

使用 Provider 封装从根组件的 render 方法返回的内容:

¥Use Provider to wrap what you return from your root component's render method:

<Provider myObject={this.myObject}>
<NavigationContainer>{/* Screen configuration */}</NavigationContainer>
</Provider>

这将允许你通过 inject 函数从应用中的任何 React 组件访问 myObject,这非常有用。

¥this will allow you to access myObject from any React component in the application through the inject function which can be quite useful.

使用 observer 函数封装所有呈现可观察数据的组件。这将确保组件在渲染的数据发生更改后重新渲染。

¥Use observer function to wrap all components that render observable data. This will make sure the components re-render once the data they render changes.

¥Navigation params

应用中的屏幕通常取决于参数。React Navigation 允许你从一个屏幕 发送参数 到另一个屏幕。这些参数存储在导航状态中。但是,为了持久保存导航状态,它需要可序列化。此要求不适用于 MST,因为 MST 对象是复杂的对象,React Navigation 不知道如何(反)序列化它们。在本指南中,我们将通过自己存储导航参数来解决这个问题。

¥Screens in your application often depend on params. React Navigation allows you to send params from one screen to another. These params are stored in the navigation state. However, in order to persist the navigation state, it needs to be serializable. This requirement does not play well with MST, because the MST objects are complex objects and React Navigation doesn't know how to (de)serialize them. In this guide, we will work around this by storing the navigation params ourselves.

这意味着,我们不是将参数从一个屏幕发送到另一个屏幕(例如使用 props.navigation.navigate('MyScreen', { complexMSTObject })),而是将参数存储到导航存储中,然后在不发送任何参数的情况下进行导航,在目标屏幕上,我们将从以下位置选取参数导航存储。

¥This means that rather than sending the params from one screen to another (eg. with props.navigation.navigate('MyScreen', { complexMSTObject })) we will store the params to a navigation store, then navigate without sending any params, and on the target screen, we'll pick the params up from the navigation store.

举个例子,导航存储可能类似于:

¥To give an example, the navigation store may look similar to this:

import { types, onSnapshot, getRoot } from 'mobx-state-tree';
import { Product } from '../models/Product';
import { User } from '../models/User';

export const NavigationStore = types
.model('NavigationStore', {
productDetailScreenParams: types.map(
types.model('ProductDetailScreenParams', {
product: types.optional(types.safeReference(Product)),
})
),
userProfileScreenParams: types.model('UserProfileScreenParams', {
user: types.maybe(types.safeReference(User)),
}),
})
.actions(self => ({
...
}));

请注意,userProfileScreenParams 是带有 user 条目的简单模型,而 productDetailScreenParamsProductDetailScreenParams 模型的映射。我们选择这种数据形式的原因是我们的应用中只有一个用户配置文件屏幕,它从 userProfileScreenParams 读取其参数。productDetailScreenParams 是一张地图,因为应用可以在堆栈上包含多个产品屏幕。每个屏幕都指向地图中保存的 Product 实例。地图中的按键是 React Navigation keys:将 key 视为路由的标识符。

¥Note that userProfileScreenParams is a simple model with a user entry, while productDetailScreenParams is a map of ProductDetailScreenParams model. The reason we chose this shape of data is that we only have a single user profile screen in our app which reads its params from userProfileScreenParams. productDetailScreenParams is a map because the app can have several product screens on a stack. Each screen points to a Product instance saved in the map. The keys into the map are the React Navigation keys: think of the key as of an identifier of the route.

你的导航存储也可能只是一张地图,对于每个屏幕(无论是产品还是用户配置文件屏幕),我们都存储其导航参数。这是 示例应用 中采取的方法。

¥Your navigation store may also be just one map where for each screen (regardless if it is a product or user profile screen), we store its navigation params. This is the approach taken in the sample app.

概括

¥Summary

  • 你可以在 React Native 应用中将 React Navigation 与 MobX State Tree 结合使用

    ¥you can use React Navigation with MobX State Tree in a React Native app

  • 使用 Provider 组件以及 injectobserver 函数将 MobX 或 MST 与 React 连接起来

    ¥use the Provider component and the inject and observer functions to wire up MobX or MST with React

  • 可以保留整个应用状态并在 JS 重新加载时恢复它

    ¥it's possible to persist the entire application state and restore it upon JS reload