MobX observable with dynamic data

3.8k views Asked by At

I have the following class

export default class BaseStore {
  @observable model ;

  @action updateStore(propertyName, newValue) {
    this.model[propertyName] = newValue;
  }
}

In child classes I add layers to the observable model, such as :

model.payment.type = 'credit card'

My react component doesn't render automatically when this happen, it does however, if I has a top level data such as:

model.Type = 'CreditCard'

I am new to MobX, and read that I need to make use of map() but I am unable to find a decent example that explain how to use it.

1

There are 1 answers

2
Tholle On

If you know all the keys that the model will have, you can just initialize them with a null value, and the observer components will re-render.

Example (JSBin)

class BaseStore {
  @observable model = {
    type: null
  };

  @action updateStore(propertyName, newValue) {
    this.model[propertyName] = newValue;
  }
}

const baseStore = new BaseStore();

@observer
class App extends Component {
  componentDidMount() {
    setTimeout(() => baseStore.model.type = 'CreditCard', 2000);
  }

  render() {
    return <div> { baseStore.model.type } </div>;
  }
}

If you don't know all the keys of model beforehand, you can use a map like you said:

Example (JSBin)

class BaseStore {
  model = observable.map({});

  @action updateStore(propertyName, newValue) {
    this.model.set(propertyName, newValue);
  }
}

const baseStore = new BaseStore();

@observer
class App extends Component {
  componentDidMount() {
    this.interval = setInterval(() => {
      const key = Math.random().toString(36).substring(7);
      const val = Math.random().toString(36).substring(7);
      baseStore.updateStore(key, val);
    }, 1000);
  }

  componentWillUnmount() {
    clearInterval(this.interval);
  }

  render() {
    return <div> 
      { baseStore.model.entries().map(e => <div> {`${e[0]} ${e[1]}` } </div>) } 
    </div>;
  }
}