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应用程序中的状态管理解决方案。
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 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背后的理念是:*“应该从应用程序状态派生出任何东西。 自动。” *
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 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();
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 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.
请注意,所有状态修改必须仅通过操作来完成。
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 。
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
的事实使它成为其依赖项之一,足以在依赖项发生变化时触发该函数。
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分钟)时,就会打印出他可能不会来的信息。
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:
reaction
是autorun
一种变体,可以对函数中使用的数据(依赖性)进行更多控制。 它接受两个函数参数和选项的第三个参数:
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
We’ll understand the working of MobX by creating a React Native app in three simple steps:
我们将通过三个简单的步骤创建一个React Native应用程序来了解MobX的工作原理:
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:
如果尚未创建项目,请按照以下步骤操作:
$ react-native init UnsplashDemo
or, using Expo:
或使用Expo:
$ expo init UnsplashDemo
$ npm install mobx mobx-react
$ react-native run-<your-os>
Or, using Expo:
或者,使用Expo:
$ expo start
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();
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
来呈现图像列表。 它还将显示通过简单的切换开关添加到我们的收藏夹的图像。
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响应的更多信息。
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
了可观察的text
而setData
了可观察的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:
到目前为止,我们已经使用了observers
, observables
和actions
。 让我们添加一个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!
我们已经了解了observables
, actions
, observers
,并computed
在MobX性能,并成功通过构建一个简单的使用作出React原生应用。 我希望您在学习MobX时玩得开心,并且本教程对您入门React Native + MobX很有帮助。 编码愉快!
翻译自: https://www.digitalocean.com/community/tutorials/react-mobx-react-native-simplified
mobx react