React Native Blueprints
上QQ阅读APP看书,第一时间看更新

Defining actions

There will be two types of actions in our app: those affecting a specific component's state and those affecting the general app state. We want to store the latter somewhere out of the component's code, so we can reuse and easily maintain them. An extended practice in MobX (and also Redux or Flux) apps is to create a file named actions.js, where we will store all the actions modifying business logic for our app. 

In the case of our RSS reader, the business logic revolves around feeds and entries, so we will capture all the logic dealing with these models in this file: 

/*** actions.js ** */

import store from './store';
import xml2json from 'simple-xml2json';

export async function fetchFeed(url) {
const response = await fetch(url);
const xml = await response.text();
const json = xml2json.parser(xml);
return {
entry:
(json.feed && json.feed.entry) || (json.rss &&
json.rss.channel.item),
title:
(json.feed && json.feed.title) || (json.rss &&
json.rss.channel.title),
updated: (json.feed && json.feed.updated) || null,
};
}

export function selectFeed(feed) {
store.selectFeed(feed);
}

export function selectEntry(entry) {
store.selectEntry(entry);
}

export function addFeed(url, feed) {
store.addFeed(url, feed);
}

export function removeFeed(url) {
store.removeFeed(url);
}

Since actions modify the general app state, they will need to access the store. Let's take a look at each action separately:

  • fetchFeed: When a user wants to add a feed to the RSS reader, he will need to pass the URL, so the app can download the details for that feed (feed title, list of latest entries, and when it was updated for the last time). This action is responsible for retrieving this data (formatted as an XML document) from the supplied URL and transforming that data into a JSON object with a standard format for the app. Fetching the data from the supplied URL will be performed by fetch, a built-in library in React Native, which is used to make HTTP requests to any URL. Since fetch supports promises, we will use async/await to handle the asynchronous behavior and simplify our code. Once the XML document containing the feed's data is retrieved, we will convert that data into a JSON object using simple-xml2json, a very lightweight library for this kind of needs. Finally, the action returns a JSON object containing only the data we will really need in our app (title, entries, and last update time).
  • selectFeed: Once the user has added one or more feeds to the reader, she should be able to select one of them to get the list of the latest entries for that feed. This action just saves the details for a specific feed in the store, so it can be used by any screen interested in displaying data related to that feed (that is, the FeedDetail screen).
  • selectEntry: Similar to selectFeed, a user should be able to select one of the entries in a feed to get the details for that specific entry. In this case, the screen displaying that data will be EntryDetail as we will see in a later section.
  • addFeed: This action requires two parameters: the URL for a feed and the feed's detail. These parameters will be used to store the feed in the list of saved feeds so that it will be available globally in our app. In the case of this app, we decided to use the URL as the key which stores the details for the feed, as it is a unique property of any RSS feed.
  • removeFeed: A user can also decide that they don't want a specific feed in the RSS reader anymore and therefore we need an action to remove the feed from the list of feeds. This action only requires the URL for the feed to be passed as a parameter, since we stored the feed using the URL as an ID to uniquely identify the feed.