mobx react_带有React Native的MobX,已简化

阳航
2023-12-01

mobx react

State management is the core of any React application and as React is just a UI library, we need something to take care of the state of our app. State management can become troublesome and it is easy to create unmanageable React applications because of inconsistent state.

状态管理是任何React应用程序的核心,并且由于React只是一个UI库,我们需要一些东西来照顾我们应用程序的状态。 状态管理可能会变得麻烦,并且由于状态不一致,很容易创建无法管理的React应用程序。

In this article, we will learn about how to use MobX as our state management solution in a React Native application.

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

什么是国家管理? (What is State Management?)

A State is just the data that your app is dealing with. State saves the data that a component requires and it influences how the component gets rendered. State management is the process of managing that data. Monitoring and retrieving data in a particular app can be difficult and that’s where state management libraries come to the rescue. There are multiple ways to manage states like using Redux or the React Context API, but here we’ll cover MobX.

状态只是您的应用程序正在处理的数据。 状态保存组件所需的数据,它会影响组件的呈现方式。 状态管理是管理该数据的过程。 监视和检索特定应用程序中的数据可能很困难,因此状态管理库可助您一臂之力。 有多种方法可以管理状态,例如使用Redux或React Context API ,但是在这里我们将介绍MobX

什么是MobX? (What is MobX?)

MobX is a state management library that can be used with any JavaScript framework. React and MobX are powerful together and work as a complete framework. MobX provides the mechanism to store and update the application state that React Native then uses to render the components. The Philosophy behind MobX is: *“Anything that can be derived from the application state, should be derived. Automatically.”*

MobX是一种状态管理库,可以与任何JavaScript框架一起使用。 React和MobX强大在一起,可以作为一个完整的框架工作。 MobX提供了一种机制来存储和更新React Native随后用来渲染组件的应用程序状态。 MobX背后的理念是:*“应该从应用程序状态派生出任何东西。 自动。” *

核心理念 (Core concept)

Derivations form the backbone of MobX which enables us to discard the repeated state. The idea is to:

派生形成MobX的主干,这使我们能够丢弃重复的状态。 这个想法是:

Find minimal state (observable state), derive everything (derived state) and never turn the state into more state.

查找最小状态(可观察状态),派生一切(派生状态),并且永远不要将状态变成更多状态。

MobX at its core has three important concepts: Observables, Actions, and Reactions. A Store contains these three which then is used by the React Native application.

MobX的核心是三个重要概念: Observables , Actions和Reactions 。 商店包含这三个,然后由React Native应用程序使用。

可观察的 (Observables)

Observables with MobX are just containers that hold the core state of our application. The idea is to make an object able to emit new changes to which the observer can react. You can achieve this with the @observable decorator. Let’s imagine we have a variable named count that changes over time. We can make it observable simply by:

MobX的可观察对象仅仅是保持我们应用程序核心状态的容器。 这样做的目的是使对象能够发出观察者可以做出React的新变化。 您可以使用@observable装饰器来实现。 假设我们有一个名为count的变量,该变量会随时间变化。 我们可以通过以下方式使其变得可观察:

// import observable from mobx
import { observable } from "mobx";

//create a store with count observable
class Store {
  @observable
  count = 0;
}

//export Store
export default new Store();

计算的可观察物 (Computed Observables)

Remember the principle of MobX, *“Find minimal state (observable state), derive everything (derived state)”*. The values that can be derived from already defined observables are computed values. MobX avoids inconsistency of state by discouraging the creation of more states. Imagine our count variable holds the number of minutes by which something is delayed. We can add a computed delay message that gets derived from the observable count.

请记住MobX的原理,“ *“找到最小状态(可观察状态),派生一切(派生状态)” *”。 可以从已经定义的可观察值派生的值是计算值。 MobX通过阻止创建更多状态来避免状态不一致。 想象一下,我们的count变量保存了延迟某分钟的时间。 我们可以添加一个computed延迟消息,该消息是从可观察的count得出的。

import { observable, computed } from "mobx";

class Store {
  @observable
  count = 0;

  @computed
  get delayMessage = () => {
    return 'The train is delayed by' + this.count;
  };
}

export default new Store();

Here, @computed is working as a getter function deriving its value from count. delayMessage will automatically emit changes as the value of count changes.

在这里, @computed用作getter函数,从count派生其值。 delayMessage count更改时, delayMessage将自动发出更改。

动作 (Actions)

Actions are simply functions that modify the state. MobX supports uni-directional data flow, it means that once the action changes state, it automatically updates all the views which are consuming that state. Let’s add an action that updates over the count variable as the delay increases.

动作只是修改状态的简单函数。 MobX支持单向数据流,这意味着一旦操作更改了状态,它就会自动更新使用该状态的所有视图。 让我们添加一个action ,该action会随着延迟的增加而对count变量进行更新。

Store {
import { observable, computed, action } from "mobx";

class Store {
 @observable
  count = 0;

  @computed
  get delayMessage = () => {
    return 'The train is delayed by' + this.count;
  };

  @action
  updateDelay = delay => {
    this.count = delay;
  };
}

export default new Store();

Note that all state modifications must be done by actions only.

请注意,所有状态修改必须仅通过操作来完成。

React (Reactions)

An observer subscribes to any change in observables and re-renders the components which use them. Reactions are just side effects of these state changes. It’s very similar to computed values but the difference is instead of computing and returning a value, a reaction simply performs a side operation. In simple words, Reactions are:

观察者订阅可观察物的任何更改,然后重新渲染使用可观察物的组件。 React只是这些状态变化的副作用。 它与计算值非常相似,但区别在于它不执行计算和返回值,而是简单地执行辅助操作。 简单来说,React是:

Side effects that should occur in reaction to state changes (component re-render)

对状态变化的React应发生的副作用(重新渲染组件)

MobX provides three main types of reaction functions: autorun, when and reaction.

MobX提供三种主要类型的React功能: 自动运行 , when和reaction 。

1.自动运行 (1. autorun)

autorun is simply a function that runs every time the state changes.

autorun只是状态每次更改时运行的功能。

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

The function runs each time the value of count changes. The key is that we are not explicitly stating that it has to watch for changes in the count variable. The fact that we have used count inside autorun makes it as one of its dependency and that’s enough to trigger the function whenever the dependency changes.

每当count更改时,该函数就会运行。 关键是我们没有明确声明必须监视count变量的变化。 我们在自动运行中使用过count的事实使它成为其依赖项之一,足以在依赖项发生变化时触发该函数。

2.什么时候 (2. when)

when triggers a side-effect whenever a certain condition is met. It takes two parameters. The first parameter is a function that gets reevaluated until it returns true and the second parameter is another function that runs once the first function returns true. A simple example could be:

每当满足特定条件when就会触发副作用。 它有两个参数。 第一个参数是要重新评估的函数,直到它返回true,第二个参数是另一个函数,一旦第一个函数返回true,该函数便会运行。 一个简单的例子可能是:

class MyResource {
  constructor() {
    when(
      // once...
      () => this.count > 60,
      // ... then
      () => console.log("Guest is too late, maybe he's not coming");
    );
  }
}

Here, when simply checks if the delay is more than an hour (60 minutes) then prints that he might not be coming.

在这里, when仅检查延迟是否超过一个小时(60分钟)时,就会打印出他可能不会来的信息。

3.React (3. reaction)

reaction is a variation of autorun which gives more control over the data (dependency) used in the function. It accepts two function arguments and a third argument of options:

reactionautorun一种变体,可以对函数中使用的数据(依赖性)进行更多控制。 它接受两个函数参数和选项的第三个参数:

  1. The first argument (the data function) watches for changes in data and returns data that is used as input for the second argument, the effect function.

    第一个参数(数据函数)监视数据的变化,并返回用作第二个参数(效果函数)的输入的数据。
  2. The second function accepts the data received by the first function as the first argument and perform side effects but only when the data function returns a new value. It also receives a second argument which can be used to dispose of the reaction during execution.

    第二个函数接受第一个函数接收的数据作为第一个参数,并且仅在数据函数返回新值时才执行副作用。 它还接收第二个自变量,该自变量可用于在执行期间处置React。

The following example shows a reaction that is invoked only once.

以下示例显示了仅调用一次的React。

const reactionDemo = reaction(
  () => this.count,
  (count, reaction) => {
    console.log("reaction demo: invoked. delay is " + count);
    reaction.dispose();
  }
);

this.count = 1;
// prints:
// reaction demo: invoked. delay is = 1

this.count = 2;
// prints:
// (There are no logging, because of reaction disposed. But, count continue reaction)

console.log(this.count);
// prints:
// 2

MobX在行动 (MobX in Action)

We’ll understand the working of MobX by creating a React Native app in three simple steps:

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

  1. Defining state and making it observable

    定义状态并使之可观察
  2. Creating a View that will observe for state changes

    创建一个观察状态变化的视图
  3. Modifying the state using actions

    使用动作修改状态

我们正在建设什么 (What We Are Building)

Here we’re building a simple app that gets images from Unsplash and shows them to the user. Users can also click on an image and add it to their favorites.

在这里,我们正在构建一个简单的应用程序,该应用程序从Unsplash获取图像并将其显示给用户。 用户还可以单击图像并将其添加到他们的收藏夹。

The application uses the Unsplash API to fetch random images. You can generate an API key here.

该应用程序使用Unsplash API来获取随机图像。 您可以在此处生成API密钥

If you have not created a project yet then follow the steps below:

如果尚未创建项目,请按照以下步骤操作:

  1. Create a React Native application

    创建一个React Native应用程序
$ react-native init UnsplashDemo

or, using Expo:

或使用Expo:

$ expo init UnsplashDemo
  1. Add MobX

    添加MobX
$ npm install mobx mobx-react
  1. Run the project

    运行项目
$ react-native run-<your-os>

Or, using Expo:

或者,使用Expo:

$ expo start

步骤1.定义状态并使之可观察 (Step 1. Defining State and Making it Observable)

We’re going to search for some images and save the result. Then, we’ll allow clicking on any image to add it to our favorites. Comments are self-explanatory:

我们将搜索一些图像并保存结果。 然后,我们将允许单击任何图像将其添加到我们的收藏夹。 评论是不言自明的:

// importing observables and decorate
import { decorate, observable, action } from "mobx";

class Store {
  // observable to save search query
  text = '';

  // action to update text
  updateText = (text) => {
    this.text = text;
  }

  // observable to save image response from api
  data = null;

  // action to call API and search images
  searchImages = () => {
    fetch(`https://api.unsplash.com/search/photos?client_id=${API_KEY}&page=1&query=${this.text}&orientation=landscape`)
      .then(response => response.json())
      .then(data => this.setData(data));
  };

  // observables can be modifies by an action only
  setData = (data) => {
    this.data = data;
  };
}

// another way to decorate variables with observable
decorate(Store, {
  text: observable,
  updateText: action,
  data: observable,
  searchImage: action,
  setData: action,
});

// export class
export default new Store();

步骤2.创建一个将观察状态变化的视图 (Step 2. Creating a View that Will Observe for State Changes)

Create a component ImageList.js that will render the list of images. It will also show the images added to our favorites with a simple switch toggle.

创建一个组件ImageList.js来呈现图像列表。 它还将显示通过简单的切换开关添加到我们的收藏夹的图像。

  1. Boilerplate for ImageList component:

    ImageList组件的样板:
import React from "react";
import { View, TextInput, Button, FlatList } from 'react-native';

// imports inject and observer from 'mobx-react':
import { inject, observer } from "mobx-react";

// components receive Store values as props which we will inject while exporting
function ImageList(props) {
  // destructure variables from store to use 
  const { text, updateText, data, searchImages } = props.store;
  return (
    <>
      <TextInput // TextInput to get search query from user
        style={styles.input} 
        value={text}
        onChangeText={updateText}
      />
      <Button // Button to call API
          title="Search"
          style={styles.button}
          onPress={searchImages}
        />
      />
      <FlatList      
        data={data.results} // response from API
        keyExtractor={(item) => item.id}
        renderItem={({ item }) => (
          <ImageView // reusable component to render image
            source={{ uri: item.urls.small }} // passing the url
            onPress={() => {}} // action to add item to favorite
          />
        )}
      />
    </>
  );
}

// inject Store as props to ImageList and make it observe changes in Store
export default inject("store")(observer(ImageList));

We are just taking input from TextInput and calling the Unsplash search API by pressing the Button. The response is getting saved in the data observable and we are using that in the FlatList component to render a list of images. Simple, right? Now let’s move on to adding images to our favorites.

我们只是从TextInput接收输入,然后通过按Button调用Unsplash搜索API。 响应将保存在可观察的data ,我们在FlatList组件中使用它来呈现图像列表。 简单吧? 现在,让我们继续将图像添加到收藏夹中。

Go to unsplash.com/developers to learn more about the Unsplash API response.

请访问unsplash.com/developers,以了解有关Unsplash API响应的更多信息。

步骤3.使用操作修改状态 (Step 3. Modifying the State Using Actions)

As we know, actions are responsible for modifying state. So far, the updateText mutated the text observable and setData mutated the data observable. Now we want to add images to our favorites, it means that we need one observable to store the state and one action to mutate this state. Let’s add them.

众所周知, 动作负责修改状态。 到目前为止, updateText了可观察的textsetData了可观察的data 。 现在我们想将图像添加到favorites ,这意味着我们需要一个可观察的状态来存储状态,并需要一个操作来改变该状态。 让我们添加它们。

import { decorate, observable, action } from "mobx";

class Store {
  text = '';
  updateText = (text) => {...};

  data = null;
  searchImages = () => {...};

  setData = (data) => {...};

  // array to save favourite images
  favorites = [];

  // action to add images to favorites
  addToFavorite = (image) => {
    this.favorites.push(image);
    this.data = null;
    this.text = '';
  };
}

decorate(Store, {
  text: observable,
  updateText: action,
  data: observable,
  searchImage: action,
  setData: action,
  //adding decorators
  favorites: observable,
  addToFavorite: action,
});

export default new Store();

Now we’ll update our View for these added observables and actions. We want to clear previously searched images and show the added favorite image, this can be done simply by:

现在,我们将为这些添加的可观察对象和操作更新视图。 我们想要清除以前搜索的图像并显示添加的收藏夹图像,这可以通过以下简单方法完成:

// previous destructuring
const { favorite, addToFavorite} = this.props.store
return (
  <>
  {/* TextInput and Button added earlier */}
  {/* If data is available then show search results otherwise show the favorite images */}
  {data ?
    <FlatList // To render list of images
      style={styles.container}
      data={data.results}
      keyExtractor={(item) => item.id}
      renderItem={({ item }) => (
        <ImageView
          source={{ uri: item.urls.small }}
          onPress={() => addToFavorite(item.urls.small)} // action to add url to favorite
        />
      )}
    /> :
    <FlatList
      style={styles.container}
      data={favorites}
      keyExtractor={(item, index) => index.toString()}
      renderItem={({ item }) => (
        <ImageView
          source={{ uri: item }} // render favorite images
        />
      )}
    />
  }
  </>
);

We’ve used observers, observables and actions so far. Let’s add a computed to show the number of images added to favorites. computed works like a getter function to get derived state from the observable. It can be added as:

到目前为止,我们已经使用了observersobservablesactions 。 让我们添加一个computed以显示添加到收藏夹的图像数量。 computed工作方式类似于getter函数,以从可观察对象获取派生状态。 可以添加为:

import { decorate, observable, action, computed } from "mobx";

class Store {
  // previously added value
  get getFavoriteCount() {
    return this.favorites.length;
  }
}

decorate(Store, {
  // previously added values
  getFavoriteCount: computed,
});

export default new Store();

Let’s quickly add it to our View also:

让我们也快速将其添加到我们的视图中:

const { getFavoriteCount } = this.props.store;

return (
  // TextInput, Button
  <Text style={styles.count}>
    Images added: {getFavoriteCount}
  </Text>
  // FlatList
);

Now, the last thing we have to do is provide store in Provider to the root component. Our root file will look like this:

现在,我们要做的最后一件事是在Provider中为根组件提供store 。 我们的根文件如下所示:

import React from 'react';
import ImageList from './src/container/ImageList';

// imports Provider and store
import { Provider } from 'mobx-react';
import store from './src/store';

const App = () => {
  return (
    <Provider store={store}>
      <ImageList />
    </Provider>
  );
};

export default App;

That’s it. Let’s see a GIF of our app in action:

而已。 让我们来看一下我们应用程序的GIF:



We’ve learned about observables, actions, observers, and computed properties in MobX and successfully used them by building a simple React Native app. I hope you had fun learning MobX and this tutorial was helpful in getting you started with React Native + MobX. Happy coding! ‍

我们已经了解了observablesactionsobservers ,并computed在MobX性能,并成功通过构建一个简单的使用作出React原生应用。 我希望您在学习MobX时玩得开心,并且本教程对您入门React Native + MobX很有帮助。 编码愉快! ‍

翻译自: https://www.digitalocean.com/community/tutorials/react-mobx-react-native-simplified

mobx react

 类似资料: