React Redux is the official UI binding library for Redux. It provides a set of utilities that help you integrate a Redux store with your React components. While Redux can be used with any UI layer, React Redux makes it seamless to connect your React application to the Redux store, enabling efficient state management for complex applications.
Why Use React Redux?
1. Performance Optimizations: React Redux implements several performance optimizations under the hood, ensuring that your components only re-render when the data they are subscribed to actually changes. It avoids unnecessary re-renders that can occur with manual Redux subscriptions.
2. Simplified Component Interaction: It abstracts away the direct interaction with the Redux store, providing a declarative way for React components to read data from the store and dispatch actions.
3. Developer Experience: It offers hooks (`useSelector`, `useDispatch`) and a Higher-Order Component (`connect`) that simplify the process of connecting components to the Redux store.
Core Concepts and APIs:
1. `Provider` Component: This component is usually rendered once at the root of your React component tree. It takes the Redux `store` as a prop and makes it available to all nested components that need to access it. Any component wrapped by `Provider` can then connect to the store.
```jsx
import { Provider } from 'react-redux';
import store from './store'; // Your Redux store
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
```
2. `connect` HOC (Higher-Order Component): This is the older but still widely used way to connect React components to the Redux store. It's a function that takes two optional arguments, `mapStateToProps` and `mapDispatchToProps`, and returns another function that you then call with your component.
* `mapStateToProps(state, ownProps)`: A function that receives the entire Redux `state` and the component's `ownProps`. It should return an object that contains the data from the store that your component needs. These values will be passed as props to your component.
* `mapDispatchToProps(dispatch, ownProps)`: A function that receives the Redux `dispatch` function and the component's `ownProps`. It should return an object where each key is a prop name and each value is a function that dispatches a Redux action. These functions will also be passed as props.
3. `useSelector` Hook: This hook allows you to extract data from the Redux store state. You pass it a 'selector' function, which takes the entire Redux state as an argument and returns the piece of state you want.
```jsx
import { useSelector } from 'react-redux';
function MyComponent() {
const count = useSelector(state => state.counter.value);
// ...
}
```
4. `useDispatch` Hook: This hook returns a reference to the `dispatch` function from the Redux store. You can then use this `dispatch` function to dispatch actions.
```jsx
import { useDispatch } from 'react-redux';
function MyComponent() {
const dispatch = useDispatch();
const handleClick = () => {
dispatch({ type: 'INCREMENT' });
};
// ...
}
```
When to Use Hooks vs. `connect`:
* Hooks (`useSelector`, `useDispatch`) are generally recommended for functional components as they provide a cleaner, more direct way to interact with the store. They are simpler to use and often lead to less boilerplate.
* `connect` is suitable for class components or when you need more advanced features like customizing `shouldComponentUpdate` logic via `mergeProps` or having the `dispatch` prop automatically injected without explicit `mapDispatchToProps` (though this is less common with hooks).
React Redux makes state management in React applications more structured, predictable, and maintainable, especially for larger projects.
Example Code
```javascript
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import App from './App';
// Redux Reducer
const counterReducer = (state = { value: 0 }, action) => {
switch (action.type) {
case 'INCREMENT':
return { ...state, value: state.value + 1 };
case 'DECREMENT':
return { ...state, value: state.value - 1 };
case 'INCREMENT_BY_AMOUNT':
return { ...state, value: state.value + action.payload };
default:
return state;
}
};
// Create Redux Store
const store = createStore(counterReducer);
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
{/* Provide the Redux store to the entire application */}
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
// src/App.js
import React from 'react';
import Counter from './Counter';
function App() {
return (
<div style={{ textAlign: 'center', marginTop: '50px' }}>
<h1>React Redux Counter Example</h1>
<Counter />
</div>
);
}
export default App;
// src/Counter.js
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
function Counter() {
// Use useSelector to extract data from the Redux store state
const count = useSelector(state => state.value);
// Use useDispatch to get the dispatch function
const dispatch = useDispatch();
return (
<div>
<h2>Count: {count}</h2>
<div>
<button
onClick={() => dispatch({ type: 'INCREMENT' })}
style={{ margin: '5px', padding: '10px 20px', fontSize: '16px' }}
>
Increment
</button>
<button
onClick={() => dispatch({ type: 'DECREMENT' })}
style={{ margin: '5px', padding: '10px 20px', fontSize: '16px' }}
>
Decrement
</button>
<button
onClick={() => dispatch({ type: 'INCREMENT_BY_AMOUNT', payload: 5 })}
style={{ margin: '5px', padding: '10px 20px', fontSize: '16px' }}
>
Increment by 5
</button>
</div>
</div>
);
}
export default Counter;
```








react-redux