Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mobx @computed functions with parameters

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?

like image 883
Johnson Smithson Avatar asked Mar 21 '18 04:03

Johnson Smithson


People also ask

What is @computed in MobX?

(@)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.

Does MobX work with functional components?

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.

What does @action do MobX?

@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)'.

What is toJS in MobX?

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.


2 Answers

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)
like image 185
Johnson Smithson Avatar answered Sep 27 '22 23:09

Johnson Smithson


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.

like image 25
Sandrogo Avatar answered Sep 27 '22 21:09

Sandrogo