React Redux Fundamentals
Redux is a state management library, similar to Vuex/Pinia in Vue. It uses reducers to manage application state.
Tags
Redux in React
Redux is a state management library, similar to Vuex/Pinia in Vue. It uses reducers to manage application state.
This page is useful to remember some concepts about Redux. I written it while I was studying Redux in React, and I intend to visit here to remember something if I forget.
Get Data
useSelector
- get data from the store
Post Data
useDispatch
- dispatch an action to the store
Action
There are 2 attributes that we need to pass to dispatch an action, and it's the same thing that we will receive to treat in reducers.
type
- the type of action that we want to dispatch, describes the nature of the action, indicating the event triggering it.payload
- the data that we want to pass to the reducer, e.g., email and password for a login
NOTE
Updates to a reducer trigger a reactive behavior, causing components using the updated data to re-render.
Get Started (without Redux toolkit)
Setup
- In any React project, install the following packages:
yarn add -D redux react-redux
- Create a store file, and use the
createStore
function to create a store.
// store.js
import { createStore } from 'redux'
import rootReducer from './rootReducer'
export default createStore(rootReducer)
- Create a root reducer file, and use the
combineReducers
function to combine all reducers.
// rootReducer.js
import { combineReducers } from 'redux'
import userReducer from './user/reducer'
const rootReducer = combineReducers({
// here we can add any number of reducers as we need
userReducer
})
export default rootReducer
- Create a reducer file, and use the
createReducer
function to create a reducer.
// user/reducer.js
const initialState = {
currentUser: null
}
const userReducer = (state = initialState, action) => {
switch (action.type) {
case 'user/login':
return {
...state,
currentUser: action.payload
}
case 'user/logout':
return {
...state,
currentUser: null
}
default:
return state
}
}
export default userReducer
- Provide the redux to whole application. We need to add it to the root component.
// app/page.jsx
import { Provider } from 'react-redux'
import store from './redux/store'
const App = () => {
return (
<Provider store={store}>
<div>...</div>
</Provider>
)
}
After that, we can use the useSelector
and useDispatch
hooks to get and post data to the store.
Get Data
Use reducer in any place of your app.
// components/navbar.jsx
import { useSelector } from 'react-redux'
const Navbar = () => {
const { currentUser } = useSelector(rootReducer => rootReducer.userReducer)
return (
<>
{currentUser && <div>{currentUser.name}</div>}
</>
)
}
Post Data
Use dispatch in any place of your app.
// components/login.jsx
import { useDispatch } from 'react-redux'
const Login = () => {
const dispatch = useDispatch()
const handleLogin = () => {
dispatch({
type: 'user/login',
payload: {
email: 'john-doe@email.com',
password: '123456'
}
})
}
return (
<>
<button onClick={ handleLogin }>Login</button>
</>
)
}
Selectors
Selectors are functions that we can use to get data from the store. It's useful to avoid repeating the same code in different places of the app. It can be useful to apply some logic like .map, .filter, and etc.
// user/selectors.js
export const selectCurrentUser = state => state.userReducer.currentUser
// components/navbar.jsx
import { useSelector } from 'react-redux'
import { selectCurrentUser } from './user/selectors'
const Navbar = () => {
const currentUser = useSelector(selectCurrentUser)
return (
<>
{currentUser && <div>{currentUser.name}</div>}
</>
)
}