Creating an api store
Note we have also created an `IBook` interface to provide some type safety for the data we are dealing with.
HTTP layer#
We will start connecting our app to our server to persist and retrieve data. In React Native you can now use the fetch
interface to do HTTP requests. This comes already integrated, but some devices have problems with it, and the API is slightly awkward.
We'll go with a better alternative, the Axios HTTP client library. Its API is a bit easier to use and it never fails, so let's start by adding it as a dependency into our project.
yarn add axios
Next we will create a new store in the stores
folder. Go ahead and create an Api.store.ts
file, with the following content:
// src/stores/Api.store.ts
import axios from 'axios';
import {IRootStore} from 'Store';
export let createApiStore = (root: IRootStore) => {
let store = {
fetchBooks: async () => {
const res = await axios.get('http://localhost:3000/book')
return res.data
},
addBook: async (title: string) => {
try {
const res = await axios.post(
'http://localhost:3000/book',
{title}
)
return res.data
} catch(e) {
console.warn(`error creating book`, e)
}
}
};
return store;
};
This store follows a similar structure to the previous UI store we created. This time we start by importing the axios dependency. Then our IRootStore
interface to make the create function type-safe.
However, you can see that in this store we are not using makeAutoObservable
, because we don't have any state to keep track of for now, but at some point you could also track your requests at this level. The beauty of MobX is that it makes it trivial to add and observe state without too much fuss.
Next we create a fetchBooks
call. This is a function that will query the GET
endpoint of our mock server. It is an marked with the async
prefix, thus making async code (such as network calls) easier to read by allowing us to use the await
keyword. Inside this function we simply call axios (with await
as a prefix) and passing it the full URL of our server. As the last step we simply return the data to whoever called the function (Axios takes care of parsing the JSON and putting it in the data
field of the returned object).
Last we add an addBook
function, which will just take the title of a book. The axios call is a bit different (we call .post
instead of .get
), and as a second parameter we pass an object with the title of our book - this object will be stringified into JSON and the server will take care of adding a date to it.
You can also see we have added minimal error handling to the addBook
function, with a try/catch block, in case the server returns an error. It's up to you on which level of abstraction you want to handle your errors. I would recommend keeping the API store as stateless as possible and handling errors on the calling stores, because most of the time you want to provide the user with some feedback in case something goes wrong. That might include some business logic, like displaying different types of alerts, specific error messages and so on.
API store#
We can now update our root store to contain our new API store:
// src/Store.ts
import { createContext, useContext } from "react"
import { createApiStore } from "stores/Api.store"
import { createUIStore } from "stores/UI.store"
export interface IRootStore {
ui: ReturnType<typeof createUIStore>,
api: ReturnType<typeof createApiStore>
}
export let createRootStore = (): IRootStore => {
let store: any = {}
store.ui = createUIStore(store)
store.api = createApiStore(store)
return store
}
We can now import the new createApiStore
function at the top of the file. Same as when we created the UI store, on our first pass on the root store, we need to add the return type of the create function into the IRootStore
interface. And finally on the body of the function, we can add a new key .api
where we create an instance of the ApiStore
.
Now you see the power of giving access to the root store from the children stores. From our UI store, we can now directly call the API layer of our app, effectively containing HTTP internals and just dealing with responses. Let's modify our UI store to use the new API store:
This page is a preview of Building React Native Apps for Mac