DEV Community

Cover image for Managing React State Like A Superhero 🦸
Majd-sufyan
Majd-sufyan

Posted on • Updated on

Managing React State Like A Superhero 🦸

The state is an important concept in React, as it allows components to store and manage data that can change over time. Properly managing state can help make your React application more efficient and easier to maintain. In this article, we will explore different ways to manage state in React and provide code examples for each method.

1- Using the useState Hook:

One of the most common ways to manage state in React is by using the useState hook. This hook allows you to add state to functional components, which were previously unable to have state. Here is an example of how to use the useState hook:

import React, { useState } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

In this example, we are using the useState hook to create a piece of state called count, which is initially set to 0. The useState hook returns an array with two elements: the current value of the state (in this case, count) and a function to update the state (in this case, setCount). We can use the setCount function to update the value of count by passing a new value as an argument.

2- Using the useReducer Hook:

Another way to manage state in React is by using the useReducer hook. This hook is similar to the useState hook, but it allows you to manage complex state logic with reducers, which are functions that take in the current state and an action, and return a new state. Here is an example of how to use the useReducer hook:

import React, { useReducer } from 'react';

const initialState = { count: 0 };

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
}

function Example() {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div>
      <p>You clicked {state.count} times</p>
      <button onClick={() => dispatch({ type: 'increment' })}>
        Increment
      </button>
      <button onClick={() => dispatch({ type: 'decrement' })}>
        Decrement
      </button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

3- Using the useContext Hook:
Another way to manage the state in React is by using the useContext hook in combination with the createContext function. The createContext the function allows you to create a context object, which can be used to pass data down the component tree without the need for props drilling. The useContext hook allows you to access the context object from a functional component. Here is an example of how to use them createContext && useContext hooks:

import React, { createContext, useContext } from 'react';

const CountContext = createContext();

function Example() {
  const count = useContext(CountContext);

  return (
    <div>
      <p>You clicked {count} times</p>
    </div>
  );
}

function App() {
  const [count, setCount] = useState(0);

  return (
    <CountContext.Provider value={count}>
      <Example />
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </CountContext.Provider>
  );
}
Enter fullscreen mode Exit fullscreen mode

4- Using a Higher-Order Component:

Another way to manage the state in React is by using a higher-order component (HOC). A HOC is a function that takes a component as an argument and returns a new component with additional functionality. Here is an example of how to use a HOC to manage the state:

import React from 'react';

function withState(WrappedComponent) {
  return class extends React.Component {
    state = { count: 0 };

    increment = () => {
      this.setState({ count: this.state.count + 1 });
    }

    render() {
      return (
        <WrappedComponent
          count={this.state.count}
          increment={this.increment}
          {...this.props}
        />
      );
    }
  };
}

function Example(props) {
  return (
    <div>
      <p>You clicked {props.count} times</p>
      <button onClick={props.increment}>
        Click me
      </button>
    </div>
  );
}

const EnhancedExample = withState(Example);

function App() {
  return (
    <EnhancedExample />
  );
}

Enter fullscreen mode Exit fullscreen mode

In this example, we are using a HOC called withState to add state management functionality to the Example component. The withState HOC returns a new component that has a count state and an increment function, which updates the count state. The Example component receives the count and increment props from the HOC and uses them to render the component.

5- Using a State Management Library:
Finally, another way to manage the state in React is by using a state management library.

Using a state management library is a popular approach to managing the state in larger React applications. A state management library is a separate package that provides additional functionality for managing the state, such as support for handling asynchronous actions and managing a global state.

One popular state management library for React is Redux. Redux is a predictable state container for JavaScript applications that helps you write applications that behave consistently. It works by creating a store that holds the application's state and provides functions for updating the state in a predictable way.

Here is an example of how to use Redux to manage the state in a React application:

import React from 'react';
import { createStore } from 'redux';
import { Provider, connect } from 'react-redux';

const initialState = { count: 0 };

function reducer(state = initialState, action) {
  switch (action.type) {
    case 'INCREMENT':
      return { count: state.count + 1 };
    case 'DECREMENT':
      return { count: state.count - 1 };
    default:
      return state;
  }
}

const store = createStore(reducer);

function Example(props) {
  return (
    <div>
      <p>You clicked {props.count} times</p>
      <button onClick={props.increment}>
        Increment
      </button>
      <button onClick={props.decrement}>
        Decrement
      </button>
    </div>
  );
}

function mapStateToProps(state) {
  return {
    count: state.count
  };
}

function mapDispatchToProps(dispatch) {
  return {
    increment: () => dispatch({ type: 'INCREMENT' }),
    decrement: () => dispatch({ type: 'DECREMENT' })
  };
}

const EnhancedExample = connect(
  mapStateToProps,
  mapDispatchToProps
)(Example);

function App() {
  return (
    <Provider store={store}>
      <EnhancedExample />
    </Provider>
  );
}
Enter fullscreen mode Exit fullscreen mode

In this example, we are using Redux to create a store that holds the application's state and a reducer function that updates the state in a predictable way. We are then using the connect function from the react-redux library to connect the Example component to the Redux store. The connect function returns a new component that receives the state and dispatch functions as props. The Example component uses the count prop to render the component and the increment and decrement props to update the state.


In conclusion, there are several different ways to manage the state in React, each with its own advantages and disadvantages. It is important to choose the right approach for your specific use case and to consider factors such as the complexity of your state, the size of your application, and the needs of your team.

Top comments (0)