Redux - rs-hash/Senior GitHub Wiki
- Redux is a library for managing state using same techniques as useReducer
- useReducer has single reducer function vs Redux has multiple Reducer function
- Redux store -> Dispatch fn -> multiple Reducer -> State
- In Redux, if we want to change state in any way, dispatch is called
- Redux toolkit is a wrapper around plain redux
- Redux toolkit simplifies the action type creation process
Sure, here's a simple example of using Redux Toolkit in a React project, broken down into steps:
Step 1: Set Up Your React Application
Create a new React application using Create React App or your preferred setup method:
npx create-react-app redux-toolkit-example
cd redux-toolkit-example
Step 2: Install Dependencies
Install Redux Toolkit, React Redux, and Redux DevTools Extension:
npm install @reduxjs/toolkit react-redux
Step 3: Create Your Redux Store and Slice
In Redux Toolkit, you'll define slices that contain both the reducer and action creators for a specific piece of state. Let's create a simple counter slice.
src/counterSlice.js:
import { createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: 0,
reducers: {
increment: (state) => state + 1,
decrement: (state) => state - 1,
},
});
export const { increment, decrement } = counterSlice.actions;
export default counterSlice.reducer;
Step 4: Create the Redux Store
Configure your Redux store using configureStore
from Redux Toolkit and include your counter reducer:
src/store.js:
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './counterSlice';
const store = configureStore({
reducer: {
counter: counterReducer,
},
});
export default store;
Step 5: Create Your React Component
Create a simple React component that uses the Redux store to display and update the counter.
src/App.js:
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement } from './counterSlice';
function App() {
const counter = useSelector((state) => state.counter);
const dispatch = useDispatch();
return (
<div className="App">
<h1>Counter: {counter}</h1>
<button onClick={() => dispatch(increment())}>Increment</button>
<button onClick={() => dispatch(decrement())}>Decrement</button>
</div>
);
}
export default App;
Step 6: Connect Your App to the Redux Store
Wrap your application with the Provider
component from react-redux
to make the Redux store available to your components.
src/index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import store from './store';
import App from './App';
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
Step 7: Run Your Application
Start your application using npm start
or yarn start
. You should see a simple counter app that allows you to increment and decrement the counter using Redux Toolkit.
That's it! You've successfully set up a simple React application with Redux Toolkit. This example demonstrates the core steps of using Redux Toolkit, but you can expand on this foundation by adding more slices, reducers, and actions to manage your application's state.
Here's a simple example of using classic Redux in a React project, broken down into steps:
Step 1: Set Up Your React Application
Create a new React application using Create React App or your preferred setup method:
npx create-react-app classic-redux-example
cd classic-redux-example
Step 2: Install Dependencies
Install Redux and React Redux:
npm install redux react-redux
Step 3: Create Redux Actions and Reducers
In classic Redux, you'll define actions and reducers separately. Let's create a simple counter example.
src/actions.js:
// Define action types
export const INCREMENT = 'INCREMENT';
export const DECREMENT = 'DECREMENT';
// Action creators
export const increment = () => ({ type: INCREMENT });
export const decrement = () => ({ type: DECREMENT });
src/reducers.js:
import { INCREMENT, DECREMENT } from './actions';
// Initial state
const initialState = {
count: 0,
};
// Reducer function
const counterReducer = (state = initialState, action) => {
switch (action.type) {
case INCREMENT:
return { ...state, count: state.count + 1 };
case DECREMENT:
return { ...state, count: state.count - 1 };
default:
return state;
}
};
export default counterReducer;
Step 4: Create the Redux Store
Combine your reducers and create the Redux store:
src/store.js:
import { createStore } from 'redux';
import counterReducer from './reducers';
const store = createStore(counterReducer);
export default store;
Step 5: Create Your React Component
Create a React component that uses the Redux store to display and update the counter.
src/App.js:
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement } from './actions';
function App() {
const count = useSelector((state) => state.count);
const dispatch = useDispatch();
return (
<div className="App">
<h1>Counter: {count}</h1>
<button onClick={() => dispatch(increment())}>Increment</button>
<button onClick={() => dispatch(decrement())}>Decrement</button>
</div>
);
}
export default App;
Step 6: Connect Your App to the Redux Store
Wrap your application with the Provider
component from react-redux
to make the Redux store available to your components.
src/index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import store from './store';
import App from './App';
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
Step 7: Run Your Application
Start your application using npm start
or yarn start
. You should see a simple counter app that allows you to increment and decrement the counter using classic Redux.
Classic Redux and Redux Toolkit both serve the purpose of state management in a React application, but they have different approaches and levels of abstraction. Here are the key differences between them with examples:
1. Boilerplate Code:
-
Classic Redux: In classic Redux, you need to write a significant amount of boilerplate code to set up your actions, reducers, store configuration, and connect components to the store. Actions and reducers are often defined in separate files, leading to additional imports and more code to maintain.
-
Redux Toolkit: Redux Toolkit significantly reduces boilerplate code. It provides utility functions like
createSlice
andconfigureStore
that streamline the process of defining actions, reducers, and creating the store. Actions and reducers are often colocated within a single slice, making code more concise and maintainable.
Classic Redux Example:
// actions.js
export const INCREMENT = 'INCREMENT';
export const DECREMENT = 'DECREMENT';
export const increment = () => ({ type: INCREMENT });
export const decrement = () => ({ type: DECREMENT });
// reducers.js
const initialState = { count: 0 };
const counterReducer = (state = initialState, action) => {
switch (action.type) {
case INCREMENT:
return { ...state, count: state.count + 1 };
case DECREMENT:
return { ...state, count: state.count - 1 };
default:
return state;
}
};
Redux Toolkit Example:
// counterSlice.js
import { createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: { count: 0 },
reducers: {
increment: (state) => {
state.count += 1;
},
decrement: (state) => {
state.count -= 1;
},
},
});
2. Immutability:
-
Classic Redux: In classic Redux, you must ensure immutability when updating the state in reducers. Typically, you create new objects or arrays to represent the updated state.
-
Redux Toolkit: Redux Toolkit simplifies immutability by allowing you to directly mutate the state within reducers. It uses the Immer library under the hood to handle immutability in a more intuitive way.
3. Store Configuration:
-
Classic Redux: In classic Redux, you configure the store manually and add middleware, such as Redux Thunk, for handling asynchronous actions.
-
Redux Toolkit: Redux Toolkit's
configureStore
function simplifies store configuration. It comes preconfigured with commonly used middleware, including Redux Thunk, making it easier to handle asynchronous actions.
4. Redux DevTools:
-
Classic Redux: You need to configure and enable Redux DevTools Extension separately in classic Redux.
-
Redux Toolkit: Redux Toolkit integrates seamlessly with Redux DevTools Extension, and you don't need to set it up separately.
5. Testing:
-
Classic Redux: Testing reducers and actions in classic Redux can be straightforward, but it requires additional setup and mocking.
-
Redux Toolkit: Redux Toolkit provides utilities for testing your slices and actions, making it easier to write unit tests.
6. Migration:
-
Classic Redux: If you have an existing codebase using classic Redux, migrating to Redux Toolkit can be a manual process and may require refactoring.
-
Redux Toolkit: Redux Toolkit offers tools and guides for migrating from classic Redux to Redux Toolkit, making the transition smoother.
In summary, Redux Toolkit is designed to simplify and improve the developer experience when working with Redux. It reduces boilerplate code, encourages best practices, and provides a more intuitive API for defining actions and reducers. While classic Redux offers more flexibility and control, Redux Toolkit is an excellent choice for most projects due to its productivity benefits.