状态管理是任何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的工作:
- 定义状态并使其可观察
- 创建将观察状态变化的视图
- 使用操作修改状态
我们正在建设什么
在这里,我们正在构建一个简单的应用程序,从Unsplash
获取图像并向用户显示它们。
<$>[注] 该应用程序使用 Unsplash API 来获取随机图像. 您可以 在这里生成 API 密钥。
如果您尚未创建项目,请遵循以下步骤:
创建一个 React Native 应用程序
1$ react-native init UnsplashDemo
或者使用Expo:
1$ expo init UnsplashDemo
添加MobX
1$ npm install mobx mobx-react
- 运行项目
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.** 到目前为止,更新文本突变了可观察的text
和setData
突变了可观察的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:
我们已经了解了MobX中的可观察
,行动
,观察者
和计算
属性,并通过构建一个简单的React Native应用程序成功地使用它们。