Developer: javascript, typescript, React, ... I love to discover new things, exploring code of libraries and understand how things work. Fan of creative hobbies :)
Thanks for detailed post, I found it very useful. I tried to use the "under the hood" implementation of context-selector. 1) Is it possible that on first run (of react-native app) there always are 2 renders per consumer caused by wrong initial (default) value returned by useContextSelector? I found that first time it returns a "ref" object (with "current" property), then the expected value. I think in function createProvider it should be:
...constcontextValue=useRef({value:valueRef.current,// <<=== ADDED .current HERE
Developer: javascript, typescript, React, ... I love to discover new things, exploring code of libraries and understand how things work. Fan of creative hobbies :)
2) when I use a context with 2 props: theme and lang, whenever I change several times the same prop (ie. lang) only the "lang consumer" rerender as expected. When I update one prop (ie. lang) then the other prop (ie. theme) then the app rerender both props consumers, opposite of what I was expecting: lang consumer shouldn't rerender on theme change... If I "follow" updating theme value, only theme consumer rerender, but each time I modify "the other prop", both (all) consumers rerender... Below code sample:
Developer: javascript, typescript, React, ... I love to discover new things, exploring code of libraries and understand how things work. Fan of creative hobbies :)
Indeed, it's really strange. I have tried on snack.expo.dev/ and it has a weird behavior. If I chose the Web device it works fine but not on Android and iOS.
It seems to be due to the fact of always calling setSelectedValue in useContextSelector. Because if I condition it it's working.
I will try to deep dive more and will come back to you ;)
@romaintrotard Thanks for a detailed Post. Here is the point i observed, deleting Consumer component is not doing any trick. The trick is the value passed into a value of OriginalProvider. It is a ref whose value never change so the consumer below are not notified automatically. we notify them manually via own listener.
Developer: javascript, typescript, React, ... I love to discover new things, exploring code of libraries and understand how things work. Fan of creative hobbies :)
Glad you liked the Post :) Yep deleting the Consumer has no effect on the implementation. Everything is based on the the Observer pattern that I named badly subscription / notification pattern in the article. This pattern is used in numerous libraries: react-redux, jotai, ...
Thanks for a great article! I was wondering how this library work under the hood and then I found this article in first page of google search :) But I have 1 concern when reading your implementation: If I change setSelectedValue(() => newSelectedValue); to setSelectedValue(newSelectedValue); the code won't work as expected anymore and throw error. Can you explain why? Because I see no difference between those.
It's the optimal version of the React Context with Selector, which only re-renders the components that observe the changed value. This works on both Web and Mobile.
Am facing hard time to follow through this, like how different pieces are coming together!
Glad you liked the article :)
Thanks for detailed post, I found it very useful.
I tried to use the "under the hood" implementation of context-selector.
1) Is it possible that on first run (of react-native app) there always are 2 renders per consumer caused by wrong initial (default) value returned by useContextSelector? I found that first time it returns a "ref" object (with "current" property), then the expected value.
I think in function createProvider it should be:
First of all thanks for the read and your interest in the subject :)
1) I don't code with React native but I guess it should works the same than with in JS. Do you have a repository where I can see the code ?
2) when I use a context with 2 props: theme and lang, whenever I change several times the same prop (ie. lang) only the "lang consumer" rerender as expected.
When I update one prop (ie. lang) then the other prop (ie. theme) then the app rerender both props consumers, opposite of what I was expecting: lang consumer shouldn't rerender on theme change...
If I "follow" updating theme value, only theme consumer rerender, but each time I modify "the other prop", both (all) consumers rerender...
Below code sample:
Indeed, it's really strange. I have tried on snack.expo.dev/ and it has a weird behavior. If I chose the
Web
device it works fine but not onAndroid
andiOS
.It seems to be due to the fact of always calling
setSelectedValue
inuseContextSelector
. Because if I condition it it's working.I will try to deep dive more and will come back to you ;)
Você pode estar fazendo assim para resolver esse problema:
@romaintrotard Thanks for a detailed Post. Here is the point i observed, deleting Consumer component is not doing any trick. The trick is the value passed into a value of OriginalProvider. It is a ref whose value never change so the consumer below are not notified automatically. we notify them manually via own listener.
Glad you liked the Post :)
Yep deleting the
Consumer
has no effect on the implementation. Everything is based on the the Observer pattern that I named badly subscription / notification pattern in the article. This pattern is used in numerous libraries:react-redux
,jotai
, ...Thanks for a great article! I was wondering how this library work under the hood and then I found this article in first page of google search :)
But I have 1 concern when reading your implementation:
If I change
setSelectedValue(() => newSelectedValue);
tosetSelectedValue(newSelectedValue);
the code won't work as expected anymore and throw error.Can you explain why? Because I see no difference between those.
Thanks for your precious works.
I made a package here if anyone is interested.
npmjs.com/package/@fishbot/context...
It's the optimal version of the React Context with Selector, which only re-renders the components that observe the changed value.
This works on both Web and Mobile.
Very interesting article, thanks!
This implementation is quite complex for God sake