Skip to content

A better way to orchestrate multiple stores #146

@anacierdem

Description

@anacierdem

One of the main premises of react-sweet-state is separating things into multiple more manageable stores, thus it is important to keep individual store's state small both for readability and performance reasons. This brings a few rough corners that I think we should find a solution.

  • Using data from another store requires us to hop through store hook -> container props (jsx) -> action.

    • A good example is a store keeping the data for a list of objects. It fetches them, keeps them up to date and is the source of truth for the data. Then consider another UI where we can select some of these objects. We only keep the ids of those in another store ("list store"). It does not make sense to use the "data store" for this b/c we might have different views with different selections etc.
    • When we need some information from the data store to make a decision in the list store's actions we need to go through that chain.
  • Using actions from another store requires us to hop through store hook -> jsx (optionally -> container props -> action).

    • This is generally not a problem if the container for the store from which we want to use the actions is higher in the tree. But if the containers are more appropriate in the other direction;
      • we need to either create a new container scope and use two containers with that scope (which is not very easy to manage) to be able to provide the actions or;
      • use the view/hooks to do the logic. For example we start adding things like onSubmit={() => storeAAction().then(storeBAction)}. Which makes it hard to understand the overall flow.
      • Even if we did go for the scoped containers, we would have to pass the actions to the other container in our jsx tree and we need to go through the chain again.

Because the containers decide on which data to use it is probably not very straightforward to solve this but something like this would be great if ever possible;

import { dataStore } from '...';
const listStoreAction = () => () => {
  // This will get the store instance for the nearest "data store" container that caused the listStoreAction call
  const [state, actions] = getStore(dataStore);
}

This clearly couples the list store to the data store but this is not necessarily a bad thing. We need that store/data to execute this separate flow, while still preventing data store's users from updating when the order changes for a local part of the UI somewhere.
data store updates should cause this store to update as well though.
This is something that will get out the hands of the user on the other hand, b/c now there is no mechanism to decide when to update list store depending on the data that changed on the data store. We might also need something to do the container's update action in this case. This somewhat relates to #131.

I think this need also relates to #139 overall.

Edit: We even had a case where we needed to cross two different stores to share a piece of information a few days ago.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions