Simple `mapStateToProps` conundrum
See original GitHub issueOk, here is the case. And please correct me if I’m trying to achieve this the “wrong way”.
I have an auth
logic which looks something like this:
// logic/auth.js
export default koa({
// ... actions, path, etc.
reducers: ({ actions }) => ({
user: [null, PropTypes.object, {
[actions.setUser]: (_, user) => user,
}],
}),
});
Then I want to have a HOC
which is called CheckPermissions
and it should, given the permissionsCheckCallback
, render children only if the provided function returns true
.
Now, the way I would go about it with vanilla redux is to have the CheckPermissions
component connected with the store by giving it a mapStateToProps
function which would:
- take the
user
from the providedstate
- take the
permissionsCheckCallback
function fromownProps
- return
{ hasPermissions: permissionsCheckCallback(user) }
This way component is never rerendered even if the user changes but the permissions stay the same (optimal).
Now, I’ve started doing this in kea
by having the CheckPermissions
component (pure function really…) export this:
// components/CheckPermissions.jsx
import Auth from '../logic/auth';
import { connect } from 'kea';
export default connect({
props: [
Auth, [
'user',
],
],
})((props) => (
props.hasPermissions(props.user)
? props.children
: null
))
But, the mapStateToProps
concept is happening inside the component, not outside so it does not stop the “rerender” cycle: if the user changes - even if the permissions do not - it will trigger the render.
Now, either I’m not reading the docs right / not getting some core concept of kea
or this is not possible to do the kea
way? Sure, I can always target the user
from the global state (no need to even connect Auth
) but this is why I’m trying to use kea
, so I don’t have to think about the “global” state and bring “logic” as needed (again - this may be wrong on many levels, and kea
is not intended to be used this way).
Issue Analytics
- State:
- Created 6 years ago
- Comments:15 (6 by maintainers)
Top GitHub Comments
Hey @nikolakanacki , an interesting situation you have there 😃
First, Kea is not meant to replace Redux at every instance everywhere. Sometimes, for some special components, it can make sense to revert back to Redux’s functions. You an access all the selectors of Auth just with something like
user = Auth.selectors.user(state)
.That said, there is one way you could achieve what you’re after. I haven’t tested it, so please let me know if it works.
First, whatever prop is in
connect
should trigger a re-render when it changes. As you specifically wish to avoid that foruser
, don’t pass it toconnect
, but manually pass the selector viaAuth.selectors
toselectors
inkea({})
. Something like this:If I’m not mistaken, this should work, have access to the
hasPermissions
function in the props and to the user inAuth
, without re-rendering when any of them change, but when the final result of the selector changes.Then again, this is just a fancy abstraction over
mapStateToProps
, so it might be cleaner to just use it directly.Cheers and let me know if this works 😃
Yeah, just what I was thinking, so we get a clear picture of where the origin is. It was ~3 in the morning so I just rolled back but I think it had to do with something regarding the
connect
feature, as like it was expecting those loose useless parts of the store to be found in the store tree.I’m currently creating a tiny (batteries included but optional) admin library at the moment featuring
kea
andantd
, will get to this asap since I’m also looking forward to a fix.