使用 React Native 简化 MobX

状态管理是任何React应用程序的核心,因为React只是一个UI库,我们需要一些东西来照顾我们的应用程序的状态。

在本文中,我们将学习如何在React Native应用程序中使用MobX作为我们的状态管理解决方案。

什么是国家管理?

状态只是您的应用程序处理的数据。状态保存了组件所需的数据,并影响了组件的渲染方式。状态管理是管理该数据的过程。在特定应用程序中监控和检索数据可能很困难,这就是状态管理库的获救之地。 使用 Redux或 React Context API等多种方法来管理状态,但在这里我们将涵盖 MobX

MobX是什么?

MobX 是一个状态管理库,可以与任何 JavaScript 框架一起使用。React 和 MobX 是强大的,并作为一个完整的框架工作。MobX 提供了存储和更新应用程序状态的机制,然后 React Native 使用它来渲染组件。MobX 背后的哲学是: *`任何可以从应用程序状态中提取的东西都应该自动提取。

核心概念

衍生构成MobX的支柱,使我们能够抛弃重复状态。

寻找最小状态(可观察的状态),衍生一切(衍生状态),永不将状态转化为更多状态。

MobX的核心有三个重要的概念:观察,行动和反应.一个商店包含这三个,然后被React Native应用程序使用。

观察者

使用MobX的可观测器只是持有我们应用程序的核心状态的容器,这个想法是使一个物体能够发出新的变化,观察者可以对其做出反应。你可以通过@observable装饰器实现这一点。

 1// import observable from mobx
 2import { observable } from "mobx";
 3
 4//create a store with count observable
 5class Store {
 6  @observable
 7  count = 0;
 8}
 9
10//export Store
11export default new Store();

计算机观察

记住MobX的原则, 找到最小状态(可观察的状态),衍生一切(衍生状态). 从已经定义的可观察的值可以衍生的值是计算值。MobX通过阻止创建更多状态来避免状态的不一致。

 1import { observable, computed } from "mobx";
 2
 3class Store {
 4  @observable
 5  count = 0;
 6
 7  @computed
 8  get delayMessage = () => {
 9    return 'The train is delayed by' + this.count;
10  };
11}
12
13export default new Store();

在这里, @computed' 作为一个 getter 函数工作,其值来自 count. delayMessage将自动发出变更作为count` 变化的值。

行动

MobX支持单向数据流,这意味着一旦操作改变状态,它会自动更新消耗该状态的所有视图。

 1Store {
 2import { observable, computed, action } from "mobx";
 3
 4class Store {
 5 @observable
 6  count = 0;
 7
 8  @computed
 9  get delayMessage = () => {
10    return 'The train is delayed by' + this.count;
11  };
12
13  @action
14  updateDelay = delay => {
15    this.count = delay;
16  };
17}
18
19export default new Store();

<$>[注] 请注意,所有状态更改必须仅通过操作进行。

反应

一个观察者订阅了可观察的任何变化,并重新渲染了使用它们的组件. 反应只是这些状态变化的副作用. 它与计算值非常相似,但差异在于,而不是计算并返回一个值,反应只是执行一项副操作。

应对状态变化的副作用(组件重现)

MobX提供三种主要类型的反应函数:autorun、when 和 reaction。

1、作者

autorun只是一个函数,每次状态发生变化时都会运行。

1autorun(() => {
2  console.log('delay is', this.count);
3} );

该函数每次运行的值变化时,关键是我们没有明确指出它必须监视变量的变化。我们在 autorun 中使用的事实使它成为它的依赖之一,这就足以在依赖变化时触发该函数。

2、什么时候

它需要两个参数.第一个参数是一个函数,它被重新评估,直到它返回为 true,第二个参数是另一个函数,一旦第一个函数返回为 true。

 1class MyResource {
 2  constructor() {
 3    when(
 4      // once...
 5      () => this.count > 60,
 6      // ... then
 7      () => console.log("Guest is too late, maybe he's not coming");
 8    );
 9  }
10}

在这里,什么时候只是检查如果延迟超过一个小时(60分钟),然后打印他可能不会来。

3、反应

反应autorun的变体,它对函数中使用的数据(依赖性)给予更多的控制,它接受两个函数参数和第三个选项参数:

1、第一个参数(数据函数)监控数据的变化,并返回用于输入第二个参数的数据,即效果函数 2.第二个函数接受第一个函数接收的数据作为第一个参数,并执行副作用,但只有当数据函数返回新的值时。

下面的例子显示一个只召唤一次的反应。

 1const reactionDemo = reaction(
 2  () => this.count,
 3  (count, reaction) => {
 4    console.log("reaction demo: invoked. delay is " + count);
 5    reaction.dispose();
 6  }
 7);
 8
 9this.count = 1;
10// prints:
11// reaction demo: invoked. delay is = 1
12
13this.count = 2;
14// prints:
15// (There are no logging, because of reaction disposed. But, count continue reaction)
16
17console.log(this.count);
18// prints:
19// 2

MobX在行动中

我们将通过三个简单步骤创建React Native应用程序来了解MobX的工作:

  1. 定义状态并使其可观察
  2. 创建将观察状态变化的视图
  3. 使用操作修改状态

我们正在建设什么

在这里,我们正在构建一个简单的应用程序,从Unsplash获取图像并向用户显示它们。

<$>[注] 该应用程序使用 Unsplash API 来获取随机图像. 您可以 在这里生成 API 密钥

如果您尚未创建项目,请遵循以下步骤:

创建一个 React Native 应用程序

1$ react-native init UnsplashDemo

或者使用Expo:

1$ expo init UnsplashDemo

添加MobX

1$ npm install mobx mobx-react
  1. 运行项目
1$ react-native run-<your-os>

或者使用Expo:

1$ expo start

步骤1:定义状态并使其可观察

我们将搜索一些图像并保存结果,然后,我们将允许点击任何图像,将其添加到我们的喜好。

 1// importing observables and decorate
 2import { decorate, observable, action } from "mobx";
 3
 4class Store {
 5  // observable to save search query
 6  text = '';
 7
 8  // action to update text
 9  updateText = (text) => {
10    this.text = text;
11  }
12
13  // observable to save image response from api
14  data = null;
15
16  // action to call API and search images
17  searchImages = () => {
18    fetch(`https://api.unsplash.com/search/photos?client_id=${API_KEY}&page=1&query=${this.text}&orientation=landscape`)
19      .then(response => response.json())
20      .then(data => this.setData(data));
21  };
22
23  // observables can be modifies by an action only
24  setData = (data) => {
25    this.data = data;
26  };
27}
28
29// another way to decorate variables with observable
30decorate(Store, {
31  text: observable,
32  updateText: action,
33  data: observable,
34  searchImage: action,
35  setData: action,
36});
37
38// export class
39export default new Store();

步骤2:创建一个将观察状态变化的视图

创建一个组件ImageList.js,该组件将显示图像列表,并通过简单的切换来显示添加到我们最喜欢的图像。

图像列表组件的锅炉板:

 1import React from "react";
 2import { View, TextInput, Button, FlatList } from 'react-native';
 3
 4// imports inject and observer from 'mobx-react':
 5import { inject, observer } from "mobx-react";
 6
 7// components receive Store values as props which we will inject while exporting
 8function ImageList(props) {
 9  // destructure variables from store to use 
10  const { text, updateText, data, searchImages } = props.store;
11  return (
12    <>
13      <TextInput // TextInput to get search query from user
14        style={styles.input} 
15        value={text}
16        onChangeText={updateText}
17      />
18      <Button // Button to call API
19          title="Search"
20          style={styles.button}
21          onPress={searchImages}
22        />
23      />
24      <FlatList      
25        data={data.results} // response from API
26        keyExtractor={(item) => item.id}
27        renderItem={({ item }) => (
28          <ImageView // reusable component to render image
29            source={{ uri: item.urls.small }} // passing the url
30            onPress={() => {}} // action to add item to favorite
31          />
32        )}
33      />
34    </>
35  );
36}
37
38// inject Store as props to ImageList and make it observe changes in Store
39export default inject("store")(observer(ImageList));

我们只是从TextInput中获取输入,并通过按按钮来调用 Unsplash 搜索 API. 答案正在被保存到数据中,我们正在使用FlatList组件来渲染图像列表。

<$>[注] 访问 unsplash.com/developers以了解有关 Unsplash API 响应的更多信息。

步骤三:使用行动改变状态

正如我们所知道的, ** actions are responsible for modifying state.** 到目前为止,更新文本突变了可观察的textsetData突变了可观察的data

 1import { decorate, observable, action } from "mobx";
 2
 3class Store {
 4  text = '';
 5  updateText = (text) => {...};
 6
 7  data = null;
 8  searchImages = () => {...};
 9
10  setData = (data) => {...};
11
12  // array to save favourite images
13  favorites = [];
14
15  // action to add images to favorites
16  addToFavorite = (image) => {
17    this.favorites.push(image);
18    this.data = null;
19    this.text = '';
20  };
21}
22
23decorate(Store, {
24  text: observable,
25  updateText: action,
26  data: observable,
27  searchImage: action,
28  setData: action,
29  //adding decorators
30  favorites: observable,
31  addToFavorite: action,
32});
33
34export default new Store();

现在我们将更新我们的视图为这些添加的可观察和操作. 我们想要清除之前搜索的图像并显示添加的喜爱图像,这可以简单地通过:

 1// previous destructuring
 2const { favorite, addToFavorite} = this.props.store
 3return (
 4  <>
 5  {/* TextInput and Button added earlier */}
 6  {/* If data is available then show search results otherwise show the favorite images */}
 7  {data ?
 8    <FlatList // To render list of images
 9      style={styles.container}
10      data={data.results}
11      keyExtractor={(item) => item.id}
12      renderItem={({ item }) => (
13        <ImageView
14          source={{ uri: item.urls.small }}
15          onPress={() => addToFavorite(item.urls.small)} // action to add url to favorite
16        />
17      )}
18    /> :
19    <FlatList
20      style={styles.container}
21      data={favorites}
22      keyExtractor={(item, index) => index.toString()}
23      renderItem={({ item }) => (
24        <ImageView
25          source={{ uri: item }} // render favorite images
26        />
27      )}
28    />
29  }
30  </>
31);

到目前为止,我们已经使用了观察者,观察者行动。让我们添加一个计算,以显示添加到喜爱的图像数量。

 1import { decorate, observable, action, computed } from "mobx";
 2
 3class Store {
 4  // previously added value
 5  get getFavoriteCount() {
 6    return this.favorites.length;
 7  }
 8}
 9
10decorate(Store, {
11  // previously added values
12  getFavoriteCount: computed,
13});
14
15export default new Store();

让我们快速添加到我们的观点:

1const { getFavoriteCount } = this.props.store;
2
3return (
4  // TextInput, Button
5  <Text style={styles.count}>
6    Images added: {getFavoriteCount}
7  </Text>
8  // FlatList
9);

现在,我们要做的最后一件事就是在供应商中为根部件提供商店

 1import React from 'react';
 2import ImageList from './src/container/ImageList';
 3
 4// imports Provider and store
 5import { Provider } from 'mobx-react';
 6import store from './src/store';
 7
 8const App = () => {
 9  return (
10    <Provider store={store}>
11      <ImageList />
12    </Provider>
13  );
14};
15
16export default App;

让我们来看看我们的应用程序在行动中的GIF:

React Native app demo animated GIF


我们已经了解了MobX中的可观察,行动,观察者计算属性,并通过构建一个简单的React Native应用程序成功地使用它们。

Published At
Categories with 技术
Tagged with
comments powered by Disqus