MobX and React hooks. Getting started.
Tags: mobx, react, hooks, contextapi
Published: 2019-06-17 20:08:31

---
title: MobX and React hooks. Getting started.
published: true
description: using MobX with hooks 
tags: mobx, react, hooks, context-api
---

![](https://thepracticaldev.s3.amazonaws.com/i/4egd8rfjb6mp5usda761.jpg)

I pretty like to use [`MobX`](https://mobx.js.org/), just the way we describe a store using class, decorate observable values, actions and computed values with decorators or [`decorate`](https://mobx.js.org/refguide/modifiers.html) function and after to use stores in components anywhere I need just to inject store into component and observe state anywhere i need. And with it also has good performance.

Simple example:
```js
//Mobx Store
class CounterStore {
  @observable count = 1;

  @action increment() {
    this.count++;
  }
  
  @action decrement() {
    this.count++;
  }
}
```

```js
//index.js
const stores = {
  // all mobx stores here
}

ReactDOM.render(
  <Provider {...stores} >
    <App/>
  </Provider>
)
```

```js
// RandomComponent.js
class RandomComponent extends React.Component {
  // some stuff
}

export default inject('anyStore')(observer(RandomComponent));
```

But with the advent of react hooks we get a new library for using mobx with react - [mobx-react-lite](https://mobx-react.js.org), at the first sight at examples and docs it seems a little bit [weird](https://news.ycombinator.com/item?id=19206276), but let's move forward with docs. We can define observable local store with [useLocalStore](https://mobx-react.js.org/state-local) and observe it with [useObserver](https://mobx-react.js.org/observer-hook), so let's try it.

```js
import React from 'react';
import { useLocalStore, useObserver } from 'mobx-react-lite';

const Counter = () => {
  const counter = useLocalStore(() => ({
    count: 0,
    increment() { counter.count++; }
    decrement() { counter.count--; }
  }));

  return useObserver(() => (
    <>
      <h2>Count: {counter.count}<h2>
      <button onClick={counter.increment}>Increment</button>
      <button onClick={counter.decrement}>Decrement</button>
    </>
  ));
}

```

From the docs about `useLocalStore`:

> All properties of the returned object will be made observable automatically, getters will be turned into computed properties, and methods will be bound to the store and apply mobx [transactions(actions)](https://mobx.js.org/refguide/action.html) automatically.

Sounds cool there is no need to decorate anymore, but what about global store, inject and Provider? And again we should look at the docs

> The naming `useLocalStore` was chosen to indicate that store is created locally in the component. However, that doesn't mean you cannot pass such store around the component tree. In fact it's totally possible to tackle global state management with `useLocalStore` despite the naming. You can for example setup bunch of local stores, assemble them in one root object and pass it around the app with a help of the React Context.

It answers the questions.
1. We can use `useLocalStore` to create global store.
2. We don't need inject and Provider, instead of it just use [Context API](https://reactjs.org/docs/context.html)

####Implementation.

There are several steps:
1. Create new context.
2. Create store with `useLocalStore` and put it as a value of context provider.
3. Wrap target component with Context Provider.
4. Get context with `useContext`.
5. Use `useObserver` in the render.

Result:
{% codesandbox mobx-react-lite-example-m1cxl %}

You could noticed the store defined in the React function according to the [rules of hooks](https://reactjs.org/docs/hooks-rules.html)

With the same approach simple ToDo List: 
{% codesandbox mobx-react-lite-example2-o05cv %}

This approach works well, but here you can see a problem - the store doesn't describes itself as much as a class analog do, also there is no optional of strict mode with `configure` where only `mobx actions` can change observable values. 

```js
configure({ enforceActions: 'observed' });
```

Personally I think the pattern useful and you can noticed the same in `Vue`, where only mutations change the state and [actions](https://vuex.vuejs.org/guide/actions.html) for asynchronous operations and other heavy stuff and in the end of the operations they commit mutations.

Can we do class store and strict mode with `mobx-react-lite`?
Sure, `useLocalStore` is almost the same as instance of class store and
we can put instance of class into value of provider.

Counter with class store:
{% codesandbox mobx-react-lite-example3-yjzj1 %}

So it almost the same approach as in [`mobx-react`](https://github.com/mobxjs/mobx-react), but now we are using `Context Provider` and `useContext` instead of `inject`.

In fact we don't even need to use `Context Provider` at all, instead of it we can `createContext` with new instance of class store and export it and to inject context into any component use `useContext`.

```js
class CounterStore {
  count = 0;
  increment = () => {
    this.count++;
  };
  decrement = () => {
    this.count--;
  };
}

decorate(CounterStore, {
  count: observable,
  increment: action,
  decrement: action
});

export const counterContext = createContext(new CounterStore());

```

```js
const CountComponent = () => {
  const counterStore = useContext(counterContext);

  return useObserver(() => (
    <>
      <h2>Count {counterStore.count}</h2>
      <button onClick={counterStore.increment}>+</button>
      <button onClick={counterStore.decrement}>-</button>
    </>
  ));
};
//and no need Provider on the upper level
```

####Conclusion

I don't think it's final approach, there are a lot of stuff in `react` and `mobx-react-lite`, but the main is still to understand the concepts behind them and hooks not only new api, but they also explain what is `React`.