You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This might mitigate the need for the shallow equal check in the useMapState primitive
I have an example implementation of this in my redux-hooks lib
Designed for good TypeScript support. TypeScript is growing like crazy and the HOC based connector is and has been pain for TypeScript users. This is an awesome opportunity to serve TS users propertly.
For the curious I would engourage you to try the hook bindings here
It's more than a toy as it attempts to actually implement all the performance requirements needed for real world usage and I would really appreciate any feedback because feedback on it would help the design of these official ones too.
Reacted by Ian Obermiller, Olivier Louvignes and Tobias Pickel
Personally I lean towards not providing an API that's expected to produce objects at all, but rather a separate invocation for each selector or action creator you want to use.
// user augments this from outside,// or we need some other trick to pass out-of-band type informationinterfaceStoreState{}// 2nd argument for these is like a useMemo argument,// but defaults to [1st argument]. The reasoning is that// you usually use selectors that were defined outside the// component if they're 1-ary / creators defined outside// the component if they're 0-ary.// one useSelector per value you want to get// it, of course, also implicitly depends on the// context store's getState().functionuseSelector<T>(selector: (state: StoreState)=>T,deps?: ReadonlyArray<unknown>): T// these return their argument but bound to dispatch// the implementation is just a memoized version of something like// return typeof arg1 === 'function'// ? (...args) => dispatch(arg1(...args))// : () => dispatch(arg1)// but the types are way more complicated// first overload for thunk action creatorsfunctionuseAction<Textends(
...args: any[])=>(dispatch: any,getState: ()=>StoreState,extraArgument: any)=>any>(actionCreator: T,deps?: ReadonlyArray<unknown>): Textends(...args: infer A)=>(...args: any[])=> infer R
? (...args: A)=>R
: never// second overload for regular action creatorsfunctionuseAction<Textends(...args: any[])=>any>(actionCreator: T,deps?: ReadonlyArray<unknown>): T// lastly expect a regular actionfunctionuseAction<Textends{type: string}>(action: T,deps?: ReadonlyArray<unknown>): ()=>T
This does have the benefit of never giving you direct access to dispatch, though! Always using bound dispatchers feels way more ergonomic to me. If you want to improve usability further (such as binding certain arguments of a multi-argument action creator) you could always wrap either the input or the output in another useMemo.
This would also have the side-effect of creating a separate subscription per useSelector, though. I don't know if that's a relevant performance consideration or not.
I had an idea to share subscriptions between useSelector calls but it feels redundant:
// fake const, only exists for creating a named typedeclareconst__SubscriptionToken: unique symboltypeSubscription=typeof__SubscriptionToken// creates a ref (what the Subscription actually is) and returns itfunctionuseSubscription(): Subscription// adds itself to a list of selectors the subscription updates which is...// ...reimplementing subscriptions on top of a subscription?functionuseSelector<T>(subscription: Subscription,selector: (state: StoreState)=>T): T
The complicated part is when you have a subscription value that depends on the result of other subscriptions -- but you only need one of the subscriptions to update for the component to rerender, and at that point the other selectors will be re-invoked when the useSelector is reached.
If you really want to you can also just return an object but then you have to handle memoization yourself and you can't use useMemo (directly) for it.
constmySelector=useMemo(()=>{letpreviousreturn(state: StoreState)=>{constresult={a: state.a,b: state.a&&state.b}if(!previous||previous.a!==state.a||previous.b!==state.b){previous=result}returnprevious}},[])const{ a, b }=useSelector(mySelector)
Reacted by chris-pardy, Adam Klein, wpq0dev, Dibyo Majumdar and Rico Kahler
I also thought of a possible effect-like API but it feels dirty to use. It's "too global" as it's not necessarily coupled to your component; or even if it is, what would it mean to have multiple copies of this component mounted?
It's like a useEffect but it'd also be invoked outside the React render cycle if the store state changed. Probably too low-level / dangerous, but is roughly the equivalent of getting the store from the context and calling subscribe yourself.
useSelect which would copy the select effect API from sagas. That would let you use your existing map state to props functions with no real changes.
useDispatch which would wrap a call to bindActionCreators letting you pass either an action creator, or object to create dispatch functions.
Both hooks would use an identity function as the default first argument so the effect of calling them without arguments would be to return the entire state, or a dispatch function respectively.
I think there's lots of room for building on top of these two base hooks but why not start super simple and let the community evolve some patterns?
Partial typescript API (doing this from my phone, so excuse any oddities)
It makes no sense as a standalone hook but when combined with an active hook it opens up a whole new world of optimization techniques.
Example:
constshop=useMapState(state=>state.shops[shopId]);// Shop products is updated only when the shop itself// has been updated. So this generates the productNames// array only when the shop has updated. constproductNames=usePassiveMapState(state=>state.shop[shopId].products.map(p=>p.name),[shop],);
I don't think you can get more efficient than that. Pretty readable too.
Pretty much a microptimization but avoiding new references can save renders downstream from pure components.
Personally I lean towards not providing an API that's expected to produce objects at all, but rather a separate invocation for each selector or action creator you want to use.
// user augments this from outside,// or we need some other trick to pass out-of-band type informationinterfaceStoreState{}// 2nd argument for these is like a useMemo argument,// but defaults to [1st argument]. The reasoning is that// you usually use selectors that were defined outside the// component if they're 1-ary / creators defined outside// the component if they're 0-ary.// one useSelector per value you want to get// it, of course, also implicitly depends on the// context store's getState().functionuseSelector<T>(selector: (state: StoreState)=>T,deps?: ReadonlyArray<unknown>): T// these return their argument but bound to dispatch// the implementation is just a memoized version of something like// return typeof arg1 === 'function'// ? (...args) => dispatch(arg1(...args))// : () => dispatch(arg1)// but the types are way more complicated// first overload for thunk action creatorsfunctionuseAction<Textends(
...args: any[])=>(dispatch: any,getState: ()=>StoreState,extraArgument: any)=>any>(actionCreator: T,deps?: ReadonlyArray<unknown>): Textends(...args: infer A)=>(...args: any[])=> infer R
? (...args: A)=>R
: never// second overload for regular action creatorsfunctionuseAction<Textends(...args: any[])=>any>(actionCreator: T,deps?: ReadonlyArray<unknown>): T// lastly expect a regular actionfunctionuseAction<Textends{type: string}>(action: T,deps?: ReadonlyArray<unknown>): ()=>T
This does have the benefit of never giving you direct access to dispatch, though! Always using bound dispatchers feels way more ergonomic to me. If you want to improve usability further (such as binding certain arguments of a multi-argument action creator) you could always wrap either the input or the output in another useMemo.
This would also have the side-effect of creating a separate subscription per useSelector, though. I don't know if that's a relevant performance consideration or not.
I had an idea to share subscriptions between useSelector calls but it feels redundant:
// fake const, only exists for creating a named typedeclareconst__SubscriptionToken: unique symboltypeSubscription=typeof__SubscriptionToken// creates a ref (what the Subscription actually is) and returns itfunctionuseSubscription(): Subscription// adds itself to a list of selectors the subscription updates which is...// ...reimplementing subscriptions on top of a subscription?functionuseSelector<T>(subscription: Subscription,selector: (state: StoreState)=>T): T
The complicated part is when you have a subscription value that depends on the result of other subscriptions -- but you only need one of the subscriptions to update for the component to rerender, and at that point the other selectors will be re-invoked when the useSelector is reached.
If you really want to you can also just return an object but then you have to handle memoization yourself and you can't use useMemo (directly) for it.
constmySelector=useMemo(()=>{letpreviousreturn(state: StoreState)=>{constresult={a: state.a,b: state.a&&state.b}if(!previous||previous.a!==state.a||previous.b!==state.b){previous=result}returnprevious}},[])const{ a, b }=useSelector(mySelector)
I'm for this API a lot. On occasions, you need the dispatch (for dynamic actions that can't be treated with actionCreators), so I would add useDispatch.
I think this library should focus on the basic API to allow developers to extend with custom hooks. So caching/side-effect etc. should not be included
Personally I lean towards not providing an API that's expected to produce objects at all, but rather a separate invocation for each selector or action creator you want to use.
100% Agree on this, I think this is the direction things should generally be going with hooks, and it seems to jive with what facebook did with useState.
// these return their argument but bound to dispatch// the implementation is just a memoized version of something like// return typeof arg1 === 'function'// ? (...args) => dispatch(arg1(...args))// : () => dispatch(arg1)// but the types are way more complicated// first overload for thunk action creatorsfunctionuseAction<Textends(
...args: any[])=>(dispatch: any,getState: ()=>StoreState,extraArgument: any)=>any>(actionCreator: T,deps?: ReadonlyArray<unknown>): Textends(...args: infer A)=>(...args: any[])=> infer R
? (...args: A)=>R
: never// second overload for regular action creatorsfunctionuseAction<Textends(...args: any[])=>any>(actionCreator: T,deps?: ReadonlyArray<unknown>): T// lastly expect a regular actionfunctionuseAction<Textends{type: string}>(action: T,deps?: ReadonlyArray<unknown>): ()=>T
This feels overwrought, I suggested a simple wrapper around bindActionCreators but even if that's not exactly the API, just getting a dispatch function feels like the right level of simplicity. Something that needs to handle Thunk action creators feels overwrought.
I think it's worth going all the way back to issue #1 as a reference. Dan laid out a list of constraints that the new in-progress React-Redux API would need to follow. Here's that list:
Common pain points:
Not intuitive how way to separate smart and dumb components with <Connector>, @connect
You have to manually bind action creators with bindActionCreators helper which some don't like
Too much nesting for small examples (<Provider>, <Connector> both need function children)
Let's go wild here. Post your alternative API suggestions.
They should satisfy the following criteria:
Some component at the root must hold the store instance. (Akin to <Provider>)
It should be possible to connect to state no matter how deep in the tree
It should be possible to select the state you're interested in with a select function
Smart / dumb components separation needs to be encouraged
There should be one obvious way to separate smart / dumb components
It should be obvious how to turn your functions into action creators
Smart components should probably be able to react to updates to the state in componentDidUpdate
Smart components' select function needs to be able to take their props into account
Smart component should be able to do something before/after dumb component dispatches an action
We should have shouldComponentUpdate wherever we can
Obviously a lot of that isn't exactly relevant for hooks, but which ones are useful, and what other constraints might be good goals?
Smart / dumb components separation needs to be encouraged
I think this actually becomes less clear with hooks regardless. I think hooks makes it easier to understand and separate smart container vs dumb presentational components but the effort has to be conscious.
There should be one obvious way to separate smart / dumb components
This is it for hooks imo:
// hooks containerimportPresentationalComponentfrom'blah/PresentationalComponent';/** with hooks, you need to manually create a "container" component */exportdefaultfunctionContainer(){constprops=useReduxState(/* ... */);// not proposing this API btw, just a place holderconstaction=useReduxAction(/* ... */);return<PresentationalComponent{...props}onEvent={action}/>;}
Because you have to manually create the container component, it's less obvious that you should separate container and presentational components. For example, some users will probably think, "why not just put useReduxState in the presentational component"?
exportdefaultfunctionPresentationalComponent(){constprops=useReduxState(/* ... */);// not proposing this API btw, just a place holderconstaction=useReduxAction(/* ... */);return// ...}
I still think the separation of container and presentational components is important but I'm not sure it's possible to create an API where we can make it obvious to encourage the separation.
Maybe this is a problem solely docs can solve?
Reacted by chris-pardy, Aaron Cunnington, Anton Petkov, tydira, Juriy Zaytsev, Jose Alejandro Cardona, Ivo Raisr and Lucas Basquerotto
@adamkleingit Not knowing that the component uses Redux or not is actually better for your business logic design. Redux is an implementation detail. If your hook is called useCurrentUser, the only thing that the hook consumer should rely on is the fact that the current user will be returned. If later on you decide to switch Redux for something else, you only have to work on your custom hooks, and nowhere else.
Reacted by Esa-Matti Suuronen, Daryl Roberts, mmso, GH Romain Gonord, Paul Sachs, Leonardo Salgueiro, Markus Gritsch, John Salis, Sean Nichols, chris-pardy and 15 more
@markerikson on the related by different topic of releases would it make sense to work one (or all) of these proposals into a 7.0.0-alpha and put it up with a @next tag. Assuming that also included API compatible implementations of connect, connectAdvanced, Provider than it would be possible to use it as a drop-in replacement, and get some real world testing in order to find any lackluster APIs or performance issues.
@chris-pardy : fwiw, my focus right now is coming up with a workable internal implementation that resolves the issues described in #1177, particularly around perf. (At least, my focus outside work. Things at work are really hectic and draining right now, which isn't helping.)
I personally am ignoring the "ship a public hooks API" aspect until we have a 7.0 actually delivered. Please feel free to bikeshed and experiment with actual implementations. Goodness knows there's enough 3rd-party Redux hooks to serve as starting points and comparisons.
I will point out that any assistance folks can offer with the tasks I listed in #1177 will ultimately result in us getting to a public hooks API faster. (hint, hint)
As @markerikson suggested, I have created a PR with my hooks implementation.
For the naming, I dropped the Redux infix since most posters here seemed to like that better. I have however changed useSelect to useSelector as was suggested above (I have also prototyped a version useSelectors that allows passing multiple selectors, but decided against it since a) the code is much more simple like this, and b) it is trivial to just use multiple useSelector calls instead or just return an object in the selector).
I have also dropped the useRedux hook since it felt redundant and any line of code that isn't written is a good line of code, as it reduces complexity, improves maintainability, and can't cause bugs.
Reacted by Anton Petkov and Nikolay Dombrovskiy
Reacted by Michael Ireland, Daishi Kato, Devin Fee, Nikita Torchinskiy, mjadobson, Anton Petkov, Olivier Louvignes, Evan Kennedy and Matt Hargett
Sorry if I've missed the answer to this earlier, but what is the idea behind having the dependencies array in useAction, but not in useSelector? It would be nice if useSelector had it too as that feels more hooks-idiomatic and we wouldn't then need to use useMemo or useCallback if we include props in it.
@mungojam You didn't miss anything. It was indeed an oversight on my part that I noticed myself over the weekend, as discussed in this post. I think it makes perfect sense to add the deps to useSelector, but it might make useRedux a bit more tricky.
Would it be possible that useSelector provides some way to bail out of a rerender by passing it a ref value.
My scenario is the following: in react native apps when you use react navigation for example, unlike on the web you don’t just render the screen that the user sees but also the whole stack of screens the user navigated over to get where he is and any parallel tabs. This is necessary for animations between screens etc.. Now the issue is you don’t want to rerender a bunch of hidden screens all the time but with redux all these components are subscribed to state updates and you can’t control when they update. In the past I’d just get a flag wether the component is corresponding to the currently active screen and then add a should component update HOC via recompose after the redux connect. But with hooks this doesn’t work anymore. I’d ideally like to be able to give a ref to the useSelector hook to control wether it should update a subscription. I can’t think of a way to build a custom hook that would achieve this behavior.
@MrLoh I don't think we should do this for such an edge case. However, my idea for this situation would be to just ensure the selector returns the same value as long as the active tab is not the tab the component is nested in. As long as you have the active tab in the state, this should be trivial to achieve. It should also be possible to turn this into a custom hook to select the state inside a tab.
@Dudeonyx I don't think this would work, as it would lead to a serenader as soon as the screen becomes inactive and everything goes to an empty/loading state. Nevertheless it should be possible to create a special memoized selector that saves and returns the last state when the screen is not inView
@dimaqq Discussion has moved to #1252 but that will probably not happen, the nice thing is, it's super easy to build your own custom hooks with whatever flavor you need based on the redux hooks
Activity
esamattis commentedon Feb 8, 2019
Based on my experiments I've come up with following wishlist for the official redux hooks api:
Provide low level primitives
useMapState()- with setState like===check based render bailoutuseDispatch()- just return the dispatch functionuseStore()- Too powerful?Maybe these higher level APIs
useActionCreators()takes an actions creators object and binds it to dispatch (memoized)useSelector()- reselect like helperDesigned for good TypeScript support. TypeScript is growing like crazy and the HOC based connector is and has been pain for TypeScript users. This is an awesome opportunity to serve TS users propertly.
For the curious I would engourage you to try the hook bindings here
https://github.com/epeli/redux-hooks
It's more than a toy as it attempts to actually implement all the performance requirements needed for real world usage and I would really appreciate any feedback because feedback on it would help the design of these official ones too.
jcestibariz commentedon Feb 8, 2019
There's a similar project in the Facebook incubator: https://github.com/facebookincubator/redux-react-hook
Jessidhia commentedon Feb 8, 2019
Personally I lean towards not providing an API that's expected to produce objects at all, but rather a separate invocation for each selector or action creator you want to use.
This does have the benefit of never giving you direct access to
dispatch, though! Always using bound dispatchers feels way more ergonomic to me. If you want to improve usability further (such as binding certain arguments of a multi-argument action creator) you could always wrap either the input or the output in anotheruseMemo.This would also have the side-effect of creating a separate subscription per
useSelector, though. I don't know if that's a relevant performance consideration or not.I had an idea to share subscriptions between
useSelectorcalls but it feels redundant:The complicated part is when you have a subscription value that depends on the result of other subscriptions -- but you only need one of the subscriptions to update for the component to rerender, and at that point the other selectors will be re-invoked when the
useSelectoris reached.If you really want to you can also just return an object but then you have to handle memoization yourself and you can't use
useMemo(directly) for it.Jessidhia commentedon Feb 8, 2019
I also thought of a possible
effect-like API but it feels dirty to use. It's "too global" as it's not necessarily coupled to your component; or even if it is, what would it mean to have multiple copies of this component mounted?It's like a
useEffectbut it'd also be invoked outside the React render cycle if the store state changed. Probably too low-level / dangerous, but is roughly the equivalent of getting thestorefrom the context and callingsubscribeyourself.chris-pardy commentedon Feb 8, 2019
Thinking about this as well and would suggest:
useSelectwhich would copy the select effect API from sagas. That would let you use your existing map state to props functions with no real changes.useDispatchwhich would wrap a call tobindActionCreatorsletting you pass either an action creator, or object to create dispatch functions.Both hooks would use an identity function as the default first argument so the effect of calling them without arguments would be to return the entire state, or a dispatch function respectively.
I think there's lots of room for building on top of these two base hooks but why not start super simple and let the community evolve some patterns?
Partial typescript API (doing this from my phone, so excuse any oddities)
Full implementation (sans tests, examples, etc.) in this Gist - https://gist.github.com/chris-pardy/6ff60fdae7404f5745a865423989e0db
esamattis commentedon Feb 8, 2019
Here's an interesting API idea: Passive state mapping hook that does not subscribe to store changes at all. It only executes when the deps change.
Implementation is basically this:
It makes no sense as a standalone hook but when combined with an active hook it opens up a whole new world of optimization techniques.
Example:
I don't think you can get more efficient than that. Pretty readable too.
Pretty much a microptimization but avoiding new references can save renders downstream from pure components.
This is available for testing here.
adamkleingit commentedon Feb 9, 2019
I'm for this API a lot. On occasions, you need the dispatch (for dynamic actions that can't be treated with actionCreators), so I would add useDispatch.
I think this library should focus on the basic API to allow developers to extend with custom hooks. So caching/side-effect etc. should not be included
chris-pardy commentedon Feb 12, 2019
100% Agree on this, I think this is the direction things should generally be going with hooks, and it seems to jive with what facebook did with useState.
This feels overwrought, I suggested a simple wrapper around
bindActionCreatorsbut even if that's not exactly the API, just getting a dispatch function feels like the right level of simplicity. Something that needs to handle Thunk action creators feels overwrought.markerikson commentedon Feb 12, 2019
I think it's worth going all the way back to issue #1 as a reference. Dan laid out a list of constraints that the new in-progress React-Redux API would need to follow. Here's that list:
Obviously a lot of that isn't exactly relevant for hooks, but which ones are useful, and what other constraints might be good goals?
chris-pardy commentedon Feb 12, 2019
Feels like most of those original criteria are still relevant. I would rephrase:
As "shouldn't impact performance".
I'm concerned that hooks would be the ultimate foot-gun for:
But I'm not sure there's a good solution other than lots of evangelizing about the benefits of separation of concerns.
ricokahler commentedon Feb 12, 2019
I think this actually becomes less clear with hooks regardless. I think hooks makes it easier to understand and separate
smartcontainer vsdumbpresentational components but the effort has to be conscious.PresentationalComponent.jsconnect HOC
hooks
Also addressing
This is it for hooks imo:
Because you have to manually create the container component, it's less obvious that you should separate container and presentational components. For example, some users will probably think, "why not just put
useReduxStatein the presentational component"?I still think the separation of container and presentational components is important but I'm not sure it's possible to create an API where we can make it obvious to encourage the separation.
Maybe this is a problem solely docs can solve?
adamkleingit commentedon Feb 12, 2019
When using custom hooks predictability is an issue on all fronts.
If you see:
in your component, it's not straightforward whether this component is aware of Redux or not, unless you enforce conventions in your team, like:
saboya commentedon Feb 14, 2019
@adamkleingit Not knowing that the component uses
Reduxor not is actually better for your business logic design. Redux is an implementation detail. If your hook is calleduseCurrentUser, the only thing that the hook consumer should rely on is the fact that the current user will be returned. If later on you decide to switchReduxfor something else, you only have to work on your custom hooks, and nowhere else.chris-pardy commentedon Feb 15, 2019
@markerikson on the related by different topic of releases would it make sense to work one (or all) of these proposals into a
7.0.0-alphaand put it up with a @next tag. Assuming that also included API compatible implementations of connect, connectAdvanced, Provider than it would be possible to use it as a drop-in replacement, and get some real world testing in order to find any lackluster APIs or performance issues.markerikson commentedon Feb 15, 2019
@chris-pardy : fwiw, my focus right now is coming up with a workable internal implementation that resolves the issues described in #1177, particularly around perf. (At least, my focus outside work. Things at work are really hectic and draining right now, which isn't helping.)
I personally am ignoring the "ship a public hooks API" aspect until we have a 7.0 actually delivered. Please feel free to bikeshed and experiment with actual implementations. Goodness knows there's enough 3rd-party Redux hooks to serve as starting points and comparisons.
I will point out that any assistance folks can offer with the tasks I listed in #1177 will ultimately result in us getting to a public hooks API faster. (hint, hint)
167 remaining items
MrWolfZ commentedon Apr 19, 2019
As @markerikson suggested, I have created a PR with my hooks implementation.
For the naming, I dropped the
Reduxinfix since most posters here seemed to like that better. I have however changeduseSelecttouseSelectoras was suggested above (I have also prototyped a versionuseSelectorsthat allows passing multiple selectors, but decided against it since a) the code is much more simple like this, and b) it is trivial to just use multipleuseSelectorcalls instead or just return an object in the selector).I have also dropped the
useReduxhook since it felt redundant and any line of code that isn't written is a good line of code, as it reduces complexity, improves maintainability, and can't cause bugs.mungojam commentedon Apr 22, 2019
Very cool to see this coming into shape.
The new docs don't look quite right for the
useCallbackwithuseSelectorexample (thoughuseCallbackvs.useMemoisn't fully in my head yet):It seems like the
useCallbackis actually being used as if it wereuseMemo, when it should just be:The equivalent
useMemoversion would be as per the current example:mungojam commentedon Apr 22, 2019
Sorry if I've missed the answer to this earlier, but what is the idea behind having the dependencies array in
useAction, but not inuseSelector? It would be nice ifuseSelectorhad it too as that feels more hooks-idiomatic and we wouldn't then need to useuseMemooruseCallbackif we include props in it.MrWolfZ commentedon Apr 22, 2019
@mungojam You didn't miss anything. It was indeed an oversight on my part that I noticed myself over the weekend, as discussed in this post. I think it makes perfect sense to add the
depstouseSelector, but it might makeuseReduxa bit more tricky.MrLoh commentedon Apr 22, 2019
Would it be possible that
useSelectorprovides some way to bail out of a rerender by passing it a ref value.My scenario is the following: in react native apps when you use react navigation for example, unlike on the web you don’t just render the screen that the user sees but also the whole stack of screens the user navigated over to get where he is and any parallel tabs. This is necessary for animations between screens etc.. Now the issue is you don’t want to rerender a bunch of hidden screens all the time but with redux all these components are subscribed to state updates and you can’t control when they update. In the past I’d just get a flag wether the component is corresponding to the currently active screen and then add a should component update HOC via recompose after the redux connect. But with hooks this doesn’t work anymore. I’d ideally like to be able to give a ref to the
useSelectorhook to control wether it should update a subscription. I can’t think of a way to build a custom hook that would achieve this behavior.MrWolfZ commentedon Apr 22, 2019
@MrLoh I don't think we should do this for such an edge case. However, my idea for this situation would be to just ensure the selector returns the same value as long as the active tab is not the tab the component is nested in. As long as you have the active tab in the state, this should be trivial to achieve. It should also be possible to turn this into a custom hook to select the state inside a tab.
timdorr commentedon Apr 22, 2019
Closing this out since the code is merged in.
MrWolfZ commentedon Apr 22, 2019
@timdorr Well, it's only an alpha and I think there are still some design decisions to be made.
Dudeonyx commentedon Apr 22, 2019
@MrLoh you can conditionally pass a dud selector when a component is in the background. i.e
That way when not in view the component would never re-render due to redux state changes.
Although I can envision a few bugs potentially arising from an incorrect or stale
inViewboolean causing the state to benullwhen it shouldn't be.markerikson commentedon Apr 22, 2019
@mungojam : yup, that's what happens when I write docs at midnight and haven't actually used
useCallback()myself yet :)Everyone: since this issue has gotten way too long, I've opened up #1252 for discussion of the alpha itself. Please offer feedback there.
MrLoh commentedon Apr 22, 2019
@Dudeonyx I don't think this would work, as it would lead to a serenader as soon as the screen becomes inactive and everything goes to an empty/loading state. Nevertheless it should be possible to create a special memoized selector that saves and returns the last state when the screen is not inView
dimaqq commentedon Apr 24, 2019
Here's a crazy idea:
Provide syntax sugar with exact same behaviour as
mapStateToProps, mapDispatchToProps.P.S. I'm not experienced enough to tell if the latter is better served by context instead.
MrLoh commentedon Apr 24, 2019
@dimaqq Discussion has moved to #1252 but that will probably not happen, the nice thing is, it's super easy to build your own custom hooks with whatever flavor you need based on the redux hooks