4
votes

Recently I started using mobx with react and mobx-react library.

I want to use functional React components to create my views.

I'd like to create a helper function, that takes selector function and Component, calls inject (with selector function as parameter) and observe on that Component - effectively connecting this component to mobx-react store (taken from Provider context) and providing only needed properties for this Component.

But I can't get it to work. Action is being dispatched, but views doesn't react to this change (store attributes does change, but Component doesn't react to this change).

Here's my helper function:

import { observer, inject } from 'mobx-react';

export function connect(selectorFunction, component) {
  return inject(selectorFunction)(observer(component));
}

here's my Component:

import React from 'react';
import { connect } from 'utils';

const selector = (stores) => {
  return {
    counter: stores.counterStore.counter,
    double: stores.counterStore.double,
    increment: stores.counterStore.increment
  };
};

const Counter = ({ counter, double, increment }) => {
  return (
    <div className="counter">
      <p>{ counter }</p>
      <p className="double">{ double }</p>
      <button onClick={increment}>+1</button>
    </div>
  );
};

export default connect(selector, Counter);

and here's my store:

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

export default class Counter {
  @observable counter = 0;

  @action
  increment = () => {
    this.counter++;
  }

  @computed
  get double() {
    return this.counter * 2;
  }
}

(Not showing Provider and other simple stuff, but it is set up properly).

Thanks! Every answer is much appreciated.

1

1 Answers

4
votes

Looking at Mobx's documentation, it looks like your selector is doing things a bit wrong. It should return an object with stores, and not an object with values from stores. Try returning the actual counterStore instead:

const selector = (stores) => {
  return {
    counterStore: stores.counterStore
  };
};

And use it like this in your component:

const Counter = ({ counterStore: { counter, double, increment } }) => {
  return (
    <div className="counter">
      <p>{ counter }</p>
      <p className="double">{ double }</p>
      <button onClick={increment}>+1</button>
    </div>
  );
};