-
Notifications
You must be signed in to change notification settings - Fork 61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
zero update propagation Context #3
Comments
I understand your point. (I glanced react-sweet-state code using My preference is something like export const useReadContext = React.useContext; However, I'm not sure if it should be a stable feature, because even if @gnoff 's RFC is accepted, this feature is not provided. (correct?) |
export const useReadContext(context, selector = I => I) => selector(React.useContext(context) |
I don’t understand why you need a selector for non-updating context. Would you elaborate your use case please? |
To have a common interface to read or derive something from it. |
I hadn’t seen sweet-state until now but a few observations
Ive not personally come across a use case where reading passively is essential to correct logic or performance that couldn’t be achieved by existing tools. Is the goal here a simpler API or does the passive reading actually unlock otherwise impossible capabilities? |
The common pattern - perform an API call something onMount. You have to provide some data to component, from any source, but there is no need to ever update the component if data updates. |
My opinion is probably similar to @gnoff 's. So, it becomes something like this. const Provider = ({ children }) => {
const [state, dispatch] = useReducer(reducer, initialState)
const actions = useMemo(() => ({
increment: () => dispatch({ type: 'increment' }),
}, []);
return (
<MyContext.Provider value={{ state, actions }}>
{children}
</MyContext.Provider>
);
};
const Component = () => {
const { increment } = useContextSelector(MyContext, s => s.actions);
return (
<div><button onClick={increment}>+1</button></div>
);
}; The point is that a provider has a control on the value equality, not consumers. |
Let's imagine that we are storing URL information in the Context - current page, dozen arguments, language settings derived from used domain, and so on.
const MyDataLoader = () => {
const settings = useReadContext(urlContext, getAllSearchParams);
useEffect( () => {
loadSomeData(settings); // context data are needed only here and only once.
}, []);
}); So the case I am talking about is to execute some action once. Which is quite common in Redux world for example - display a |
If you follow exhaustive-deps, it becomes: useEffect(() => {
loadSomeData(settings);
}, [settings]); Oh, and this requires Another point of discussion (might not be directly related): const Parent = () => {
const [urlInfo, setUrlInfo] = useState({});
useEffect(() => {
setUrlInfo(fetchUrlInfoSomehow());
}, []);
return (
<urlContext.Provider value={urlInfo}>
<MyDataLoader />
</urlContext.Provider>
);
}; |
You don't have to use hooks for synchronization - tasks could be quite different. For example, it would be much easier to use mount hooks if you have to call one stuff multiple times - for example for pagination. One component will load data for a page, and will clean up it later - but you might have more than one page visible at the screen - it's just about abstractions. |
Hmmm, I don't fully understand it even with the pagination example, but let me assume there's a use case. My original hesitation is how it would be implemented after the RFC becomes real. I wonder if "obervedBits=0" allows implementing |
Probably you are right, and I could solve the problem by creating two context - one with propagation, and another without. At least I would be able to use only built-in React functions. Or |
A side note: |
(Documentation only) feature request
There is a set of cases, when you need to read context only once. Read without any future update, so no subscription is needed -
mount effect
are a great example of this.Some libraries already using this pattern, for example
sweet-state
usesreadContext
("a hack") to just get the data from React, in a same "no update" mode.I think this pattern should be documented, but it seems a bit wrong to use
useContext
to do so, as long as there are some expectations about howuseContext
is working.What do you think about
useUntrackedContextSelector
? The sameuseContextSelector
, but "untracked"?The text was updated successfully, but these errors were encountered: