-
-
Notifications
You must be signed in to change notification settings - Fork 349
Idea: get rid of the restriction on changing set of stores in Provider #745
Comments
Afaik there shouldn't be any problems with propagation as the error suggests, I think the whole impl can be as simple as: export function Provider({ children, ...newStores }) {
const stores = React.useContext(MobXProviderContext);
return <MobXProviderContext.Provider value={{ ...stores, ...newStores }}>{children}</MobXProviderContext.Provider>
} However, it will invoke all |
Another benefit of having such a simple implementation. People who peek into a source code will see there is no longer anything special about Provider and perhaps even migrate over to Context directly (which is the ultimate goal). Although |
@urugator I wonder if we apply As long as the user is passing props with the same reference there is no need to re-render Provider. If they pass something different, it will naturally allow it. |
No, because |
Wasn't really following the original convo, so might have missed it. But I am wondering: Is this there an actual use case where this is in the way? Otherwise, from personal experience, I'd keep it: It is way way easier to start with a really narrow scope / use case, and extend it if needed. Compared to: supporting all possible use cases, and than noticing that you can't do certain things (for example, optimizations) because some patterns are already out there used in the wild :). So I'd personally, if Provider is too limited to you, I would recommend just go for useContext right away. But I would keep the semantic meaning of Provider simple: it is designed for dependency injection, not for state management. State would better be managed in MobX observables :). Hence my question: is there a specific use-case problem to be solved here. Or is it more about removing the limitation for the sake of removing the limitation? In the last case I'd recommend not to do it. |
We bumped into this when @vkrol was doing a polish of unit tests and then started rewriting Provider to hooks on my suggestion and it looked suspicious there. We started digging and discovered it was there for legacy context which had a problem with it. Even the readme was mentioning it incorrectly. Obviously, there is no problem with keeping it. It's just an idea to simplify code base so people who will peek under the hood will see there is nothing special about it. |
I'm not sure the context changes would be picked up correctly by inject in
all possible setups (e.g. named stores vs. injection function), or that
those are covered by tests. So impicitly supporting this might actually
introduce some bugs / kill some optimizations. (Definitely not sure about
the last)
…On Mon, Aug 5, 2019 at 11:13 PM Daniel K. ***@***.***> wrote:
We bumped into this when @vkrol <https://github.com/vkrol> was doing a
polish of unit tests and then started rewriting Provider to hooks on my
suggestion and that check with error throw just looked suspicious there. We
started digging and discovered it was there for legacy context which had a
problem with it.
Obviously, there is no problem with keeping it. It's just an idea to
simplify code base so people who will peek under the hood will see there is
nothing special about it.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#745?email_source=notifications&email_token=AAN4NBDLYP3I4N5NZ5Y7SPTQDCJV5A5CNFSM4II7UTKKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD3TDC7A#issuecomment-518402428>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAN4NBEIKFHJPRF22Z6FRRTQDCJV5ANCNFSM4II7UTKA>
.
|
A little bit optimized impl (ref value created only once, export function Provider(props) {
const parentValue = React.useContext(MobXProviderContext)
const valueRef = React.useRef();
if (!valueRef.current) {
const { children, ...rest } = props;
valueRef.current = {
...parentValue,
...rest,
}
}
const value = valueRef.current;
if (process.env.NODE_ENV !== "production") {
const { children, ...rest } = props;
const newValue = { ...value, ...rest } // spread in previous state for the context based stores
if (!shallowEqual(value, newValue)) {
throw new Error(
"MobX Provider: The set of provided stores has changed. Please avoid changing stores as the change might not propagate to all children"
)
}
}
return (
<MobXProviderContext.Provider value={value}>{props.children}</MobXProviderContext.Provider>
)
} EDIT (don't want to reopen, so just for completeness):
export function Provider({ children, ...propsValue }) {
const contextValue = React.useContext(MobXProviderContext)
const [value] = React.useState(() => ({
...contextValue,
...propsValue,
}));
if (process.env.NODE_ENV !== "production") {
const newValue = { ...value, ...propsValue } // spread in previous value for the context based stores
if (!shallowEqual(value, newValue)) {
throw new Error(
"MobX Provider: The set of provided stores has changed. Please avoid changing stores as the change might not propagate to all children"
)
}
}
return (
<MobXProviderContext.Provider value={value}>{children}</MobXProviderContext.Provider>
)
} |
@urugator Do we really need to optimize Provider? :) I mean in most cases when it sits on top of the tree it won't even be re-rendered. And for other cases, it also doesn't happen that often unless someone is doing something terribly wrong. We had it like that and I asked @vkrol to simplify it to improve readability because the benefit seems really unimportant. Am I missing something here? I suppose let's close this, it was mostly just a wild idea. |
@mweststrate I believe that if we want to keep the restriction as it is, we need to explain the motivation as clearly as possible in the documentation, because now it is not clear and confusing. |
@vkrol I mostly agree with you, but I would dare to say that most people won't ever encounter that exception unless they are doing something terribly wrong. That error message is kinda self-explanatory imo. Also, there is already some explanation in docs (see Notes below the example). @urugator Noticed your edit. I was suggesting |
No. The message is:
But we don't know a single case where the change might not propagate.
This note does not explain anything. Conclusions:
|
We should figure this one out first...
However, is it worth it? Consider that people will over time migrate away from inject, so investing some heavy dev time into it might be a waste.
So it's probably this one and to simply explain it's for a legacy reasons :) And in case someone actually runs into that scenario (which I doubt), we can start digging. |
I agree.
OK, I will do the PR. |
…f stores (#760) * Clarify the reason why there is the restriction on changing the set of stores Fixes #745 * Update README.md Co-Authored-By: Daniel K. <[email protected]>
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs or questions. |
@mweststrate We had a discussion about the restriction on changing set of stores in
Provider
with @FredyC. What do you think about removing this restriction?The quote from the change log for
[email protected]
:a64c2d3#diff-4ac32a78649ca5bdd8e0ba38b7006a1eR11
#739 (comment)
#742 (comment)
The text was updated successfully, but these errors were encountered: