Redux Setup in Your React Project - Personal Preference
The first thing is to install libraries for redux, as you may guess:
1npm install -S redux react-redux redux-logger reselect redux-persist
redux-logger
is a redux middleware which is really really helpful in development, but it's up to you whether to use it or not.
reselect
is a memoization implementation for redux.
redux-persist
is for leveraging localStorage/sessionStorage browser APIs in redux.
Assuming that you have the react project structured in your own way, I'd create a new folder named redux
inside the src/app
folder:
1mkdir -p src/app/redux
For demonstration purposes, we gonna setup user reducer
, which is specific to user
domain.
Create a root reducer
and store
first, though.
1# inside the 'redux' folder:
2touch root-reducer.js store.js
Then create user reducer
-related files:
1# inside the 'redux' folder:
2mkdir -p user
3cd user
4touch user.reducer.js user.types.js user.actions.js user.selectors.js
Overwhelming already? Nah~ it's not, let me explain what the files do.
user.reducer.js
is a file that contains real reducer, which can be called CPU
of redux.
user.types.js
will be containing action types as variables(I'd call it mapping), which is a good convention in redux world.
user.actions.js
has real action definitions in it.
user.selectors.js
is for memoization which is a great concept for pure functions, and it's all about performance.
Here is our root-reducer.js
file:
1import { combineReducers } from 'redux';
2import { persistReducer } from 'redux-persist';
3import storage from 'redux-persist/lib/storage';
4
5import userReducer from './user/user.reducer';
6import cartReducer from './cart/cart.reducer'; // just ignore this, it's only for demonstration of redux-persist setup
7
8const persistConfig = {
9 key: 'root',
10 storage,
11 whitelist: ['cart']
12};
13
14const rootReducer = combineReducers({
15 user: userReducer,
16 cart: cartReducer,
17});
18
19export default persistReducer(persistConfig, rootReducer);
Here is our store.js
file then:
1import { createStore, applyMiddleware } from 'redux';
2import { persistStore } from 'redux-persist';
3import logger from 'redux-logger';
4
5import rootReducer from './root-reducer';
6
7const middlewares = [];
8
9if (process.env.NODE_ENV === 'development') {
10 middlewares.push(logger);
11}
12
13const store = createStore(rootReducer, applyMiddleware(...middlewares));
14
15const persistor = persistStore(store);
16
17export { store, persistor };
user.types.js
file:
1export const UserActionTypes = {
2 SET_CURRENT_USER: 'SET_CURRENT_USER'
3}
user.reducer.js
file:
1import { UserActionTypes } from './user.types';
2
3const INITIAL_STATE = {
4 currentUser: null
5}
6
7const userReducer = (state=INITIAL_STATE, action) => {
8 switch (action.type) {
9 case UserActionTypes.SET_CURRENT_USER:
10 return {
11 ...state,
12 currentUser: action.payload
13 }
14 default:
15 return state;
16 }
17}
18
19export default userReducer;
user.actions.js
file:
1import { UserActionTypes } from './user.types';
2
3export const setCurrentUser = user => ({
4 type: UserActionTypes.SET_CURRENT_USER,
5 payload: user
6})
user.selectors.js
file:
1import { createSelector } from 'reselect';
2
3const selectUser = state => state.user;
4
5export const selectCurrentUser = createSelector(
6 [selectUser],
7 (user) => user.currentUser
8)
Phew ~ it's time to set it up in our index.js
file:
1import React from 'react';
2import ReactDOM from 'react-dom';
3import { BrowserRouter } from 'react-router-dom';
4import { Provider } from 'react-redux';
5import { PersistGate } from 'redux-persist/integration/react';
6
7import './index.scss';
8import App from './App';
9import { store, persistor } from './redux/store';
10
11ReactDOM.render(
12 <React.StrictMode>
13 <Provider store={store}>
14 <BrowserRouter>
15 <PersistGate persistor={persistor}>
16 <App />
17 </PersistGate>
18 </BrowserRouter>
19 </Provider>
20 </React.StrictMode>,
21 document.getElementById('root')
22);
Let's use our redux store in any component of our application finally:
1import React from 'react';
2import { connect } from 'react-redux';
3import { createStructuredSelector } from 'reselect';
4
5import { setCurrentUser } from './redux/user/user.actions';
6import { selectCurrentUser } from './redux/user/user.selectors';
7
8const YourComponent = props => {
9 const { currentUser, setCurrentUser } = props;
10
11 //Do something fantastic with the state and the dispatch!
12
13 return (
14 <div />
15 );
16}
17
18const mapStateToProps = createStructuredSelector({
19 currentUser: selectCurrentUser
20});
21
22const mapDispatchToProps = dispatch => ({
23 setCurrentUser: user => dispatch(setCurrentUser(user))
24});
25
26export default connect(mapStateToProps, mapDispatchToProps)(YourComponent);
That's it. Once you setup the redux, it's pretty much repetitive task to use it in any corner of your application.
Happy coding! ๐