joplin-notes/joplin notion extension/Web Development/React/Redux.md
2026-11-04 00:33:23 +05:30

3.9 KiB

Redux

Sure, Redux is commonly used to manage state in complex React applications, avoiding the need to pass props deeply through nested components. Below is a simple example that illustrates how Redux can be used to share state between components without prop drilling.

Let's create a counter app where you can increase, decrease, and reset the count. We'll use three components: App (the parent component), CounterDisplay (to display the count), and CounterControls (to increase, decrease, or reset the count), showing how Redux allows them to communicate without passing props through each other directly.

Step 1: Setup

First, ensure you have Redux and React-Redux installed in your project:

npm install redux react-redux

Step 2: Create Redux Store, Reducer, and Actions

store.js

import { createStore } from 'redux';

// Reducer function
function counterReducer(state = { count: 0 }, action) {
  switch (action.type) {
    case 'INCREMENT':
      return { count: state.count + 1 };
    case 'DECREMENT':
      return { count: state.count - 1 };
    case 'RESET':
      return { count: 0 };
    default:
      return state;
  }
}

// Create and export the store
export const store = createStore(counterReducer);

Step 3: Setup Redux Provider

In your main entry file (like index.js), wrap your root component with the Provider from react-redux and pass the store to it:

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { Provider } from 'react-redux';
import { store } from './store';

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);

Step 4: Creating Components

App.js - The parent component

import React from 'react';
import CounterDisplay from './CounterDisplay';
import CounterControls from './CounterControls';

function App() {
  return (
    <div>
      <h1>Redux Counter Example</h1>
      <CounterDisplay />
      <CounterControls />
    </div>
  );
}

export default App;

CounterDisplay.js - Component to display the count

import React from 'react';
import { useSelector } from 'react-redux';

function CounterDisplay() {
  const count = useSelector(state => state.count); // Accessing count from Redux state
  return <h2>Count: {count}</h2>;
}

export default CounterDisplay;

CounterControls.js - Component to control the count

import React from 'react';
import { useDispatch } from 'react-redux';

function CounterControls() {
  const dispatch = useDispatch(); // To dispatch actions
  return (
    <div>
      <button onClick={() => dispatch({ type: 'INCREMENT' })}>Increase</button>
      <button onClick={() => dispatch({ type: 'DECREMENT' })}>Decrease</button>
      <button onClick={() => dispatch({ type: 'RESET' })}>Reset</button>
    </div>
  );
}

export default CounterControls;

Brief Explanation

In this example:

  • We've created a Redux store to hold our state, which in this case is simply a count value.
  • The counterReducer handles actions (increment, decrement, reset) to update the state accordingly.
  • The App component is our root component, rendering both the CounterDisplay and CounterControls components.
  • The CounterDisplay component uses useSelector to read the count value from the Redux store directly, without needing to receive it as a prop.
  • The CounterControls component uses useDispatch to dispatch actions that update the state, without needing to receive dispatch functions as props.

By using Redux, we've avoided the need to pass the count state or the dispatch functions through the App component, directly connecting the CounterDisplay and CounterControls components to the state they need. This simplifies the component structure and makes state management more efficient and scalable for larger applications.