Giter Club home page Giter Club logo

Comments (11)

jpeyper avatar jpeyper commented on May 28, 2024

Hi @Crazy-Ivan,

Its a bit hard to provide an example without understanding your use case a little better. To our knowledge that aren't any issues using reselect with react-redux-subspace.

Are you able to provide any code of your complex selector and how you used it with subspace, or provide a few more details on the problem you are seeing?

Have you considered using redux-subspace-wormhole to provide root state to your subspace?

from redux-subspace.

Crazy-Ivan avatar Crazy-Ivan commented on May 28, 2024

Hi @jpeyper,

redux-subspace-wormhole can be the answer. Base on documentation I see that I have to explicit map which part of the global state will be injected. Which breaks a bit open/close principle. I had to edit it every time I will need add selector which use part of the global scope, I didn't inject before.

const store = createStore(rootReducer, 
applyMiddleware(wormhole((state) => state.globalCarsCollection, 'globalCarsCollection')), 
applyMiddleware(wormhole((state) => state.globalColors, 'globalColors')), 
applyMiddleware(wormhole((state) => state.globalPrices, 'globalPrices')), 
)
export const getSomthingImportant = () => createSelector(
    scopedListOfIdsSelector, // [{carId, colorId, priceId},...]
    globalCarsCollectionSelector,
    globalColorsSelector,
    globalPricesSelector,
    (scopedListOfIds, globalCarsCollection, globalColors, globalPrices) => {
      return something
    }
);

In the example above globalCarsCollectionSelector, globalColorsSelector, globalPricesSelector are functions which expect rootState, scopedListOfIdsSelector expect scoped state. Injecting global scope into local scope is a trick which could work for reselect (if we won't have a naming collision). However, we have to be sure that we inject everything and be sure that there is no naming collision. Do you know how it could be solved?

Thank you in advance

from redux-subspace.

mpeyper avatar mpeyper commented on May 28, 2024

@Crazy-Ivan, just so I can be sure I'm understanding correctly, you want to use reselect to create a selector to use in:

a) mapStateToProps param of a connect HOC used inside a subspace
b) mapState param of a subspaced HOC
c) mapState param of a SubspaceProvider
d) other?

Base on documentation I see that I have to explicit map which part of the global state will be injected. Which breaks a bit open/close principle.

We do have a RFC open (#57) on how the wormhole api could be improved if you would like to add any thoughts you have on it (positive and/or negative).


Side note:

you don't need to use applyMiddleware so many times:

const store = createStore(rootReducer, applyMiddleware(
  wormhole((state) => state.globalCarsCollection, 'globalCarsCollection'), 
  wormhole((state) => state.globalColors, 'globalColors'), 
  wormhole((state) => state.globalPrices, 'globalPrices'), 
))

If you're really wanting access to all root values in all subspaces, you can just create a root (or whatever you want to call it) wormhole that has the entire state in it:

const store = createStore(rootReducer, applyMiddleware(wormhole((state) => state, 'root')))

The in your subspaces you can use state.root.globalCarsCollection, state.root.globalColors, state.root.globalPrices, etc. as needed.

from redux-subspace.

Crazy-Ivan avatar Crazy-Ivan commented on May 28, 2024

a) mapStateToProps param of a connect HOC used inside a subspace

from redux-subspace.

mpeyper avatar mpeyper commented on May 28, 2024

At it's core, redux-subspace is about isolating the subspace's state and actions from the rest of store. Where ever possible, I would advise against relying on global values in subspaces. Having said that global state is often necessary to meet the requirements.

a) mapStateToProps param of a connect HOC used inside a subspace

In that case your only option is to inject the global values into the subspaces state. There are two official ways this can be achieved:

  1. wormholes: global values area available to all subspaces
    const store = createStore(rootReducer, applyMiddleware(
      wormhole((state) => state.globalCarsCollection, 'globalCarsCollection'), 
      wormhole((state) => state.globalColors, 'globalColors'), 
      wormhole((state) => state.globalPrices, 'globalPrices'), 
    ))
  2. rootState param: the second parameter of the mapState prop (for either SubspaceProvider or subspaced) will be the rootState, which can be used to merge into the subspaces state
    <SubspaceProvider mapState={(state, rootState) => ({ ...state.nodeForSubspace, globalCarsCollection: rootState.globalCarsCollection, globalColors: rootState.globalColors, globalPrices: rootState.globalPrices })}>
      <ComponentToSubspace />
    </SubspaceProvider>

Now the subspace can access the global values directly in their state, i.e. state.globalCarsCollection.

As mentioned before, if you don't want to explicitly name each prop, you could introduce a root node that contains the whole rootState. This could be done in either method.

const store = createStore(rootReducer, applyMiddleware(wormhole((state) => state, 'root')))
<SubspaceProvider mapState={(state, rootState) => ({ ...state.nodeForSubspace, root: rootState })}>
  <ComponentToSubspace />
</SubspaceProvider>

Now the subspace can access the global values by pathing through the root node in their state, i.e. state.root.globalCarsCollection.

Of course, you could write your own middleware to change the getState behaviour of subspace, but this is likely overkill for your use case.

Good luck, an please let us know if something here doesn't make sense, or if there is some way you think redux-subspace can be more helpful in meeting your requirements.

from redux-subspace.

mpeyper avatar mpeyper commented on May 28, 2024

Oh, I forgot to mention about reselect...

Once the global values are in the subspace's state, you can use reselect like normal:

export const getSomthingImportant = () => createSelector(
    scopedListOfIdsSelector, // from the local state for the subspace, e.g. state.scopedListOfIds
    globalCarsCollectionSelector, // from state.globalCarsCollection or state.root.globalCarsCollection
    globalColorsSelector, // from state.globalColors or state.root.globalColors
    globalPricesSelector, // from state.globalPrices or state.root.globalPrices
    (scopedListOfIds, globalCarsCollection, globalColors, globalPrices) => {
      return something
    }
);

from redux-subspace.

Crazy-Ivan avatar Crazy-Ivan commented on May 28, 2024

Thank you, that is very helpful. One question. Is there any option to get the name of the subspace inside a wrapped component? ('react-redux-subspace')

from redux-subspace.

mpeyper avatar mpeyper commented on May 28, 2024

One question. Is there any option to get the name of the subspace inside a wrapped component? ('react-redux-subspace')

Nothing that is officially supported.

Technically, if you have access to the store directly, then it will have a namespace field on it that will be the namespace of the current subspace.

this.context.store.namespace

Note: I am in not way endorsing direct access of the store from the context. Use at your own risk of the api changing.

I am curious what the use case is that requires the component to know the namespace though. If it's common enough, we could introduce a HOC into react-redux-subspace to inject it into a component.

from redux-subspace.

mpeyper avatar mpeyper commented on May 28, 2024

Hi @Crazy-Ivan, is there anything left to do on this issue or can I close it?

from redux-subspace.

Crazy-Ivan avatar Crazy-Ivan commented on May 28, 2024

Use case: [Mobile app] I have several screens which make up one search functionality (search screen, specific filter screens, etc). Screens are connected together via navigations system in a layer above component definition. I had to use this search functionality in many places but the state should not be shared. To be able to navigate correctly between screens inside search functionality ( results screen -> main filter screen -> specific filter screen), I need to now on which namespace a user is.

from redux-subspace.

mpeyper avatar mpeyper commented on May 28, 2024

Hi @Crazy-Ivan, just wondering how you are going with this?

I'm still not sure if there is anything actionable for this item. Happy to discuss further, or close if you feel there is nothing more to do.

from redux-subspace.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.