Selectors returning functions invoke those functions
victorporof opened this issue · 5 comments
There is a bug in https://github.com/edriang/use-context-selection/blob/master/src/useContextSelection.ts#L16
For useContextSelection(Context, state => state.onFoobar);
, the onFoobar
function is executed because of useState
's overload which takes state builders as an argument.
Needless to say this isn't the intended behaviour expected by the developers, especially when compared to how react-redux works in useSelector
.
One can work around this issue by doing something like const useFixedContextSelection = (Context, selector) => useContextSelection(Context, (s) => () => selector(s));
, but it'd be nice if this was fixed in upstream.
Actually the workaround is more involved, since returning a function that selects ends up tripping up the equality checker. So while functions are not executed anymore, shallow equality would fail in unexpected ways.
Hello @victorporof, thanks writing.
I'm not sure I'm understanding your problem; could you supply a full example code? (codesandbox would be great)
The second parameter of useContextSelection
is a selector function, that receives your state as first parameter and should return whatever you need for rendering that specific component.
In the example you pasted you are trying to get onFoobar
from your state object (a.k.a. the value you stored on your Context.Provider).
So, in your component you probably are doing something like const { onFoobar } = useContextSelection(Context, state => state.onFoobar);
; at this point, onFoobar
is whatever you've stored, probably a Function.
Now, what is onFoobar
and what do you need to do with it? What is the specific thing that's not working for you?
Just try returning a function from a selector. That function will be invoked, which is bad.
const what = useContextSelection(Context, state => () => alert("should not alert"));
Thanks @victorporof, thanks for giving me that last instruction.. Now I understand what you've posted originally about the useState
overload function arguments; I wasn't aware about that, so thank you for clarifying!
For sure this is not intended and I will work to get this fixed soon (hopefully today or at least during the week).
That being said, if you need a quick workaround that will work now, you can do something like this:
const { alertFn } = useContextSelection(Context, state => ({
alertFn: () => alert("should not alert"),
});
So, you can return an object containing your function, and destructure that parameter on the returning object.
@victorporof this issue is now fixed in use-context-selection@1.4.2
, thanks for reporting!
Link to the fixing commit: 7567598