mobxjs / mobx-react

React bindings for MobX

Home Page:https://mobx.js.org/react-integration.html

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

mobX with react hooks without provider

panda0603 opened this issue · comments

commented

Hello, thanks again for the wonderful library.

Upon moving to mobx-react-lite with react hooks, I have two questions.

I have made the following structure as an example:

// animal store
// src/store/animalStore.ts

import {decorate, observable, computed} from 'mobx';

export class AnimalStore {
  animal: string[] = ['cat', 'dog', 'pig'];
  get animalSize() {
    return this.animal.length;
  }
}

decorate(AnimalStore, {
  animal: observable,
  animalSize: computed,
});

// bug store
// src/store/bugStore.ts

import {decorate, observable, computed} from 'mobx';

export class BugStore {
  bug = ['grasshoper', 'cricket', 'ant'];
  get bugSize() {
    return this.bug.length;
  }
}

decorate(BugStore, {
  bug: observable,
  bugSize: computed,
});

// src/store/index.ts

import React from 'react';
import {BugStore} from './bugStore';
import {AnimalStore} from './animalStore';

const storesContext = React.createContext({
  animalStore: new AnimalStore(),
  bugStore: new BugStore(),
});

export const useStores = () => React.useContext(storesContext);

// src/index.tsx

import React from 'react';
import {View, StyleSheet, Text, TouchableOpacity} from 'react-native';
import {observer} from 'mobx-react-lite';
import {useStores} from './store';
import {addAnimal} from './globals/helpers';

const Init: React.FC = () => {
  const {animalStore, bugStore} = useStores();

// using just animalStore for simplicity

  return (
    <View style={styles.container}>
      {animalStore.animal.map((data) => (
        <Text key={data}>{data}</Text>
      ))}
      <TouchableOpacity
        onPress={() => {
          addAnimal('giraffe', animalStore);
        }}>
        <Text>add Animal</Text>
      </TouchableOpacity>
    </View>
  );
};

export default observer(Init);
  1. Is it fine to use mobX without a provider at the top most component?
import React from 'react';
import Init from './src';

const App = () => {
  return <Init />;
};

export default App;

above is my App.tsx, which I have not used any provider, and mobX still seems to work fine.
I can call and manipulate store without any problem. Can I not use provider at all? if not, when should we use provider?

  1. Is it fine to manipulate mobX store by passing it down as an argument to a function?
// src/globals/helpers.ts

import {runInAction} from 'mobx';
import {AnimalStore} from '../store/animalStore';

export function addAnimal(item: string, store: AnimalStore) {
  runInAction(() => {
    store.animal.push(item);
  });
}

Let's say I define some utility functions in different folder to add animals to animal Store.
Since the function is not a React function component, I cannot call stores using useStores();
Is it okay to pass down stores as an argument and manipulate the stores using runInAction as above? It seems to work fine. Would there be any downsides?

Thanks very much for the help!

Please see https://mobx-react.js.org/recipes-context#multiple-global-stores

Anything that works for you is totally fine. Don't try to find some "holy grail" here, there is none. Only bunch of tradeoffs :)

commented

Thanks for the reply.
Though it works fine in my case, there may be side-effects that I have not encountered yet so it is good to know in advance if it is fine to proceed.
I have read the link you have provided, which it says

You could drop the whole Provider dance and set created store as a default value of the createContext. The reference of the store object does not need to change, so it will work in most cases. However, you might still setup a Provider for tests to battle flakiness.

'However, you might still setup a Provider for tests to battle flakiness.' I am not quite sure about what this actually means. When do we 'have' to use providers?

Side-effects or tradeoffs are always present in the development and you cannot find "the best" way without them. Sooner you accept it, sooner you will be happy :)

When do we 'have' to use providers?

That depends on so many things. For now, if you don't need a Provider, then don't use it.

commented

Let me rephrase the question then,
Any reasons 'not' to use providers?

If there aren't any gains, i.e. performance, I would be better of just using providers all the time?
Just couple of lines more to add the provider is not a problem at all.

commented

@mweststrate Thanks. Guess I will start using provider once I understand it.

What about question 2? It is okay to alter store in that fashion?

If there aren't any gains, i.e. performance, I would be better of just using providers all the time?

There are gains, but until you need them, don't worry about it. Or feel free to spend half a day reading through articles and crawling through discussions. You can start at https://kentcdodds.com/blog/?q=context

Don't optimize until you need it. Any sort of optimization always comes with tradeoffs of code complexity.

@panda0603 yeah that is perfectly fine

commented

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.