HenrikJoreteg / redux-bundler

Compose a Redux store out of smaller bundles of functionality.
https://reduxbundler.com
583 stars 46 forks source link

Replace extra args #44

Closed dhilgarth closed 5 years ago

dhilgarth commented 5 years ago

The extra args seem like a very simple dependency injection mechanism to me.
I have the situation where I need to re-create the values from extra args with new values from the store.

E.g. I have a config that is in the store and can change over time and I have classes that use this config. These classes in turn are used by action creators.

How would I go about solving this situation? So far, it seems to me as if extra args is called once and that's it.

My current solution is using a Lazy class that creates the value only when accessing it and then stores it. On each value access it checks if the config has changed since and then recreates it if necessary. But this doesn't seem very elegant to me. I would rather directly react to the CONFIG_RECEIVED action.

HenrikJoreteg commented 5 years ago

Hi @dhilgarth! Hm... so if I'm understanding correctly, you have config values stored in redux, that sometimes update? It seems like you could store your config as a redux bundle that periodically checks for updates and updates its state, then as long as you have selectors on the bundle and use that whever you need to read the state you'd be ok.

It's a bit of a footgun, but unlike regular redux, redux-bundler actually passes the entire store to action creators.

So you could do something like this:

export default {
  name: 'someBundle',
  doSomething: () => ({ store }) => {
    const configValue = store.selectConfigValue()
    // do something with config value
  }
}

Once you have a selector that returns a config value, you can also use that in a reactor:

reactShouldFetchNewStuff: createSelector(
  'selectMetadataAboutLastFetch',
  'selectConfigValue',
  (metadata, value) => {
    if (
      metadata.fetchedForValue !== value &&
      !metadata.isFetching
    ) {
      return { actionCreator: 'doFetchAgain' }
    }
})

I'm not 100% i understood you correctly, feel free to re-open this if this doesn't help.

Cheers!

dhilgarth commented 5 years ago

Hi Henrik, thanks for your timely response. It's not about the config itself but about classes that are derived from it, e.g. API wrappers whose base URL etc are stored in this configuration. My application is actually a plugin for a host application and that host application can send a new config to my application at any time.

HenrikJoreteg commented 5 years ago

Hey :) It's still just state, and you can always reference whatever state you want inside an action creator since you have access to the entire store and all of its attached methods.

Also, there's nothing saying you can't have a selector that returns a generated API wrapper. The state itself is still serializable, you're just deriving an instance from it rather than a value.

selectApiWrapper: createSelector(/
  'selectCurrentConfiguration',
  config => {
    return new ApiWrapper(config)
  }
)

then, in an action creator

doSomething: () => ({ store }) => {
  return store.selectApiWrapper('/some-path').then(res => {
    // something here
  })
}
dhilgarth commented 5 years ago

Thanks. I guess my problem is that my API wrappers are actually classes with their own internal state, so I can't recreate them in the selector. This state is long lived and contains business logic Is this maybe actually the problem? Should I put all such state in Redux instead?

HenrikJoreteg commented 5 years ago

Hard for me to say without knowing the whole situation. But the key thing to understand is that the selectors will only re-evaluate if their inputs have changed. So it's safe to create a class or update an instance of a class inside a selector because the body of the last function will only be re-evaluated if the inputs change.

Anyway, good luck! Hope you get it sorted.

On Sun, Dec 16, 2018, 03:58 Daniel Hilgarth notifications@github.com wrote:

Thanks. I guess my problem is that my API wrappers are actually classes with their own internal state, so I can't recreate them in the selector. This state is long lived and contains business logic Is this maybe actually the problem? Should I put all such state in Redux instead?

— You are receiving this because you modified the open/close state.

Reply to this email directly, view it on GitHub https://github.com/HenrikJoreteg/redux-bundler/issues/44#issuecomment-447637275, or mute the thread https://github.com/notifications/unsubscribe-auth/AAEJVUJh02yDpxO0oFl_qW_iguvQ5mmKks5u5jVxgaJpZM4ZKBhs .