I am using react-redux for my react project, apparently, there are 2 ways to use the redux state
connect or useSelector,
My redux store has a reducer for each page,
For Home Page > homePageReducer
For Message Page > messagePageReducer
For Authentication > authReducer
For User’s blog > blogReducer
For Settings > userSettingsReducer
For User’s Profile > userProfileReducer
In my top-level component or the main component, I have used a selector hook to get all the reducer and passed down the reducers as props to the required components
const {home, messages, auth, settings, blogs} = useSelector( (state:RootState) => state)
return(
<main>
<Switch>
<Route exact to={HOME_ROUTE}>
<HomeApp auth={auth} settings={settings} userProfile={userProfile}/>
</Route>
<Route exact to={CHAT_ROUTE}>
<ChatApp auth={auth} messages={messages} userProfile={userProfile}/>
</Route>
<Route exact to={BLOG_ROUTE}>
<BlogApp auth={auth} blogs={blogs} userProfile={userProfile}/>
</Route>
</Switch>
</main>
)
Is it a good architecture for my project and bring no performance issue for my project or should I use connect or useSelector hook inside those components?
What is better?
Advertisement
Answer
Redux has a very useful Style Guide explaining all of the current best practices. There are a few recommendations on that list that are applicable to your example.
Use the React-Redux Hooks API
Prefer using the React-Redux hooks API (
useSelectoranduseDispatch) as the default way to interact with a Redux store from your React components.
Connect More Components to Read Data from the Store
Prefer having more UI components subscribed to the Redux store and reading data at a more granular level. This typically leads to better UI performance, as fewer components will need to render when a given piece of state changes.
Call useSelector Multiple Times in Function Components
When retrieving data using the
useSelectorhook, prefer callinguseSelectormany times and retrieving smaller amounts of data, instead of having a single largeruseSelectorcall that returns multiple results in an object.
You definitely want to use useSelector. Rather than selecting everything in the parent and passing it down, your Route render components should take no props and get everything that they need from Redux themselves.
const App = {
return(
<Switch>
<Route exact to={HOME_ROUTE}>
<HomeApp />
</Route>
<Route exact to={CHAT_ROUTE}>
<ChatApp />
</Route>
<Route exact to={BLOG_ROUTE}>
<BlogApp />
</Route>
</Switch>
)
}
const HomeApp = () => {
const userProfile = useSelector( (state: RootState) => state.user );
// We probably don't need the whole auth object
const isLoggedIn = useSelector( (state: RootState) => !! state.auth );
// Do you need to return *every* setting? Just select what you need.
const settings = useSelector( (state: RootState) => state.settings );
...
}
You might want to create selector functions especially for commonly-accessed values like userProfile.
An alternative to modifying the current components HomeApp etc. would be to create a HomeScreen component as a wrapper around HomeApp and keep HomeApp as a pure presentational component. HomeScreen would get all of the data from Redux and call HomeApp with the correct props.