I'm new to Mobx but so far it's been working great and I've managed to get pretty far. I have a react-native application with mobx, and mobx-persist. I'm using axios to pull posts from a Wordpress site. The functionality that I'm trying to improve is an "add to favorites" feature.
Here's my PostsStore:
export default class PostsStore {
// Define observables and persisting elements
@observable isLoading = true;
@persist('list') @observable posts = [];
@persist('list') @observable favorites = [];
// Get posts from Wordpress REST API
@action getPosts() {
this.isLoading = true;
axios({
url: 'SITE_URL',
method: 'get'
})
.then((response) => {
this.posts = response.data
this.isLoading = false
})
.catch(error => console.log(error))
}
// Add post to favorites list, ensuring that it does not previously exist
@action addToFavorites(id) {
if (this.favorites.indexOf(id) === -1) {
this.favorites.push(id);
}
}
// Remove post from favorites list, ensuring that it does indeed exist
@action removeFromFavorites(id) {
if (this.favorites.indexOf(id) !== -1) {
this.favorites.remove(id);
}
}
}
In my Favorites component, which is intended to render a button to add or remove from favorites, I thought that using an @computed function would've been preferred to determine if the current post being rendered has an 'id' that has been added to the observable 'favorites' array. However, it seems that an @computed function is not allowed to take arguments (a minimum parameter would be the post's 'id' to evaluate if it is in the favorites observable array. I can accomplish the test using an @action but that doesn't seem to update the rendered screen immediately which is the objective. As the code below demonstrates, I'm forced to perform the test with an 'if' statement in the component render.
render () {
if (this.props.postsStore.favorites.includes(this.props.item.id)) {
return (
<Button
onPress={() => this.props.postsStore.removeFromFavorites(this.props.item.id)}
title="★"
/>
)
}
Does this affect my application's performance? Is there an @computed way to do what I want? Should I just not worry about this since it's kinda working?
(@)computed. Computed values are values that can be derived from the existing state or other computed values. Conceptually, they are very similar to formulas in spreadsheets. Computed values can't be underestimated, as they help you to make your actual modifiable state as small as possible.
In this tutorial, we will learn how to use MobX with React Functional Components. MobX being a very useful state management library reduces the code that needs to be written for global state management. Mobx is easy to use and quick to learn.
@action is used for functions that will change to the existing information (state), and prompts 'observers' to access the latest version of the relevant 'observable(s)'.
Usage: toJS(value) Recursively converts an observable object to a JavaScript object. Supports observable arrays, objects, Maps and primitives. It does NOT recurse into non-observables, these are left as they are, even if they contain observables.
Doing this worked:
@computed get isFavorite() {
return createTransformer(id => this.favorites.includes(id))
}
Called in my view like so:
this.props.postsStore.isFavorite(this.props.item.id)
Just for the sake of completeness: mobx-utils provides a way to use arguments in computed functions by now. You can use computedFn
and would declare your function as follows:
isFavorite = computedFn(function isFavorite(id) {
return this.favorites.includes(id)
})
Take a look at the article in the docs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With