Search code examples
javascriptecmascript-6generatormobxmobx-state-tree

Generator syntax with 'flow' in MobX State Tree


I have three actions in a MobX State Tree store: the first fetches data form the API, the second sends a POST request using the data from the API in the database, and the third takes the response and saves it to the store.

The store is comprised simply of a map of these data structures called Lists:

export const ListStore = types
  .model('ListStore', {
    lists: types.map(List),
  })

The first two actions to send the GET and POST requests work fine:

 .actions((self) => ({
    fetchTitles: flow(function* fetchTitles(params: Params) {
      const env = getStoreEnv(self);
      const { clients } = env;
      const browseParams: BrowseParams = {
        category: 'movies',
        imdb_score_min: params.filter.imdbFilterScore,
      };
      let browseResult;
      try {
        browseResult = yield clients.browseClient.fetch(browseParams);
      } catch (error) {
        console.error('Failed to fetch titles', error);
      }
      return browseResult.data.results.map((title) => title.uuid);
    }),
  }))
  .actions((self) => ({
    postList: flow(function* postList(params: Params) {
      const env = getStoreEnv(self);
      const { clients } = env;
      const titles = yield self.fetchTitles(params);
      return clients.listClient.create({
        name: params.name,
        titles,
        invites: params.invites,
        filter: params.filter,
      });
    }),
  }))

But when it comes to the third action, actually saving the List to the ListStore, no such luck. I've tried quite a few variations, but simply none of them work. Honestly I am not too familiar with generator syntax, and I even tried doing it without the generator. Here you can see my attempts:

createList: flow(function* createList(params: Params) {
  const env = getStoreEnv(self);
  const list = yield self.postList(params);
  console.log('list in createList', list.data);
  return self.lists.put(List.create({ ...list.data }, env));
  // return self.lists.set(list.id, list.data);
}),
createList: flow(function* createList(params: Params) {
  const list = yield self.postList(params);
  console.log('list in createList', list.data);
  yield self.lists.set(list.id, list.data);
}),
createList(params: Params) {
  return self.postList(params).then((list) => {
    console.log('list in createList', list.data);
    self.lists.set(list.id, list.data);
  });
},
createList: flow(function* createList(params: Params) {
  yield self.postList(params).then((list) => {
    console.log('list in createList', list.data);
    return self.lists.set(list.id, list.data);
  });
}),

I've tried with both .set() and .put(), but to no avail. I've also tried using yield and return...nothing seems to work. The data logged in console.log('list in createList', list.data); looks correct and matches the model (and if it didn't, wouldn't I get an error saying so?). No errors are logged to the console, it just silently fails.

If you can spot the error and see how this should be written, I will be extremely grateful. Thank you!


Solution

  • It turns out that the issue was not with the syntax: as you can see in the first comment by the maintainer of MST, the second version is correct.

    The problem lies in the way the model (not shown here) was created.