I want to set a property based on multiple values from my redux store. (If it makes any difference I use Rematch to handle my global store)
In my case, a boolean property called showSidebar
which is only true if several other conditions are met - as a simplified example: loggedIn === true
and userProjects.length > 0
.
The logic is fine, e.g.
const showSidebar = loggedIn && userProjects.length > 0;
...but I use this in lots of components, and every time I have to import all of the dependent properties and include the conditional logic.
How can I avoid needless duplication of logic and imported props?
I was thinking the best way may be to write my own useShowSidebar
hook, which would look something like the following:
import { useState, useEffect } from 'react';
import { useSelector } from 'react-redux';
const useShowSidebar = () => {
const loggedIn = useSelector((models) => models.model.loggedIn);
const userProjects = useSelector((models) => models.model.userProjects);
const [showSidebar, setShowSidebar] = useState(false);
useEffect(() => {
setShowSidebar(loggedIn && userProjects.length > 0);
}, [loggedIn, userProjects]);
return showSidebar;
};
export default useShowSidebar;
Would this be a sensible and efficient way to achieve this without any issues? Or is there a better way? I assume this must be a common scenario.
I feel like there should be a way to have the property showSidebar
in the global store itself as a property that is dependent upon other properties, and just import this one property into my components (using either mapStateToProps
or the more modern useSelector
hook, but I can't figure out if this is possible.
Your use of useState
causes an unneccessary rerender. Just write it all as one selector.
const useShowSidebar = () => {
const showSidebar = useSelector((state) =>
state.model.loggedIn && state.model.userProjects.length > 0
);
return showSidebar;
};
Or move it into a selector function and use that in your components:
const selectShowSidebar = (state) =>
state.model.loggedIn && state.model.userProjects.length > 0;
// in your component:
const showSidebar = useSelector(selectShowSidebar)