use-context-selector icon indicating copy to clipboard operation
use-context-selector copied to clipboard

[Question] Getting several context values at once?

Open soykje opened this issue 3 years ago • 6 comments

Hi :wave:

First things first, thx a lot for this great work! :clap: I'm still discovering it, and maybe I'm going to ask a silly question but... is there any reason why useContextSelector examples were always using the same "one call, one value" pattern:

const v1 = useContextSelector((ctx) => ctx.v1)
const v2 = useContextSelector((ctx) => ctx.v2)
const v3 = useContextSelector((ctx) => ctx.v3)
...

...which seems quite verbose to me. Couldn't we simply use a single call such as:

const { v1, v2, v3 } = useContextSelector(({ v1, v2, v3 }) => ({ v1, v2, v3 }))

Thx a lot for your answer! :pray:

soykje avatar Oct 10 '22 11:10 soykje

You can do that if you memoize the selector function. For example proxy-memoize does it for you.

import memoize from 'proxy-memoize';

const selector = memoize(({ v1, v2, v3 }) => ({ v1, v2, v3 }));

const Component = () => {
  const { v1, v2, v3 } = useContextSelector(Ctx, selector);
  // ...
};

dai-shi avatar Oct 10 '22 11:10 dai-shi

Thx for this quick answer! I must be missing something but, why should I use memoization? Aren't both patterns eqs?

soykje avatar Oct 10 '22 11:10 soykje

Because

const { v1, v2, v3 } = useContextSelector(({ v1, v2, v3 }) => ({ v1, v2, v3 }))

will trigger re-renders for any changes (like v4).

So, "one call, one value" pattern is the rule we follow. You might be interested in reading #19 discussion.

dai-shi avatar Oct 10 '22 12:10 dai-shi

Hmmm... I'm not sure to perfectly understand why, but I'll be looking for some infos within the linked discussion :+1: Thx a lot @dai-shi !

soykje avatar Oct 10 '22 12:10 soykje

Assuming you are not talking about custom equality function, const { v1, v2, v3 } = useContextSelector(({ v1, v2, v3 }) => ({ v1, v2, v3 })) is not technically easy. It's not impossible though, and that's what react-tracked does.

const { v1, v2, v3 } = useTrackedState()

react-tracked uses use-context-selector under the hood. So, they do different jobs.

dai-shi avatar Oct 10 '22 12:10 dai-shi

Ok thx a lot for all these informations, let's read (and learn) then :slightly_smiling_face:

soykje avatar Oct 10 '22 13:10 soykje

Closing as answered.

dai-shi avatar Jan 29 '23 11:01 dai-shi