DEV Community

Cover image for The Power Of Atom: Best React State Management in your projects 2023 Part One
Hasan Zohdy
Hasan Zohdy

Posted on

The Power Of Atom: Best React State Management in your projects 2023 Part One

Introduction

State management in React.js is a crucial aspect of building complex and interactive applications. It involves managing and controlling the data that changes over time within a React component or across multiple components. By using state management, we can easily handle application state, share data between components, and ensure a smooth and consistent user experience. Whether through React's built-in state or by implementing external libraries like Redux or MobX, state management empowers developers to efficiently update and synchronize data in their React applications, making them more robust and scalable.

Using Context API

The Context API in React is a built-in feature that allows developers to pass data through the component tree without explicitly passing props down the hierarchy. It provides a way to share state or other data across multiple components without the need for prop drilling.

Pros of using the Context API

  • Simplicity: The Context API simplifies the process of sharing data between components by eliminating the need for manually passing props through intermediate components.
  • Global State: Context allows developers to create global state that can be accessed by any component within the context. This is useful for managing application-level state, such as user authentication or theme preferences.
  • Avoids Prop Drilling: With Context, you can avoid the problem of prop drilling, where intermediate components need to pass props to deeply nested components that require the data.
  • Easy to Use: The Context API has a straightforward API that is easy to understand and use. It consists of a Provider component to define the data source and a Consumer component to access that data.

Cons of using the Context API

  • Performance Considerations: Context updates can trigger re-renders in components that consume the context, potentially impacting performance. It is recommended to use context sparingly and optimize the updates to prevent unnecessary re-renders.

  • Limited to React Components: The Context API is specifically designed for React components and may not be suitable for sharing data with non-React components or integrating with other libraries.

  • Reduced Component Isolation: Since Context allows data to be accessed from multiple components, it can reduce component isolation and make it harder to understand and reason about the flow of data within the application.

  • Overuse Complexity: Overusing Context and relying on it excessively can lead to complex and tightly coupled code, making it difficult to maintain and test.

Using external state management tools

So far, the most popular tool for state management is Redux, which offers great features to use over the application, however, Redux considered to be too complex when dealing with it, writing more code to achieve let's say a good achievement.

Mongez React Atom

When i started looking for a good state management tools to use in my complex application projects, mostly all available tools i used are too complex to achieve small tasks that requires a lot of coding to be written, os yes as you guessed, I MADE A NEW PACKAGE!

Why another state management?

Well, basically i consider it the most efficient and easiest tool among all available packages out there based on all developers that used it.

Here are some of the features that makes it the best:

  • Simple and easy to use
  • Can be used in any React Js/React Native application.
  • Can be used outside components.
  • Listen to atom's value change.
  • Listen to atom's object property change.
  • Lightweight in size.
  • Manages object and arrays atoms out of the box.
  • Works in SSR (Server Side Rendering) applications.

Redux VS Redux Toolkit VS React Atom

Let's see a simple example, a currency dropdown that should be displayed in the Header and Footer components, what we need to achieve here is to change the current from the Header component, the Footer component's currency dropdown is changed with the new value and vice versa.

Using Redux

Create a new file called actions.js and add the following code:

// Action Types
export const SET_CURRENT_CURRENCY = "SET_CURRENT_CURRENCY";

// Action Creators
export const setCurrentCurrency = (currency) => {
  return {
    type: SET_CURRENT_CURRENCY,
    payload: currency,
  };
};
Enter fullscreen mode Exit fullscreen mode

Create another file called reducers.js and add the following code:

import { SET_CURRENT_CURRENCY } from "./actions";

// Initial State
const initialState = {
  currentCurrency: "USD",
};

// Reducer
export const currencyReducer = (state = initialState, action) => {
  switch (action.type) {
    case SET_CURRENT_CURRENCY:
      return {
        ...state,
        currentCurrency: action.payload,
      };
    default:
      return state;
  }
};
Enter fullscreen mode Exit fullscreen mode

Now, create a new file called store.js to set up the Redux store:

import { createStore } from "redux";
import { currencyReducer } from "./reducers";

const store = createStore(currencyReducer);

export default store;
Enter fullscreen mode Exit fullscreen mode

Next, let's create the header and footer components that will display and update the current currency.

Create a new file called Header.js and add the following code:

import React from "react";
import { useSelector, useDispatch } from "react-redux";
import { setCurrentCurrency } from "./actions";

const Header = () => {
  const currentCurrency = useSelector((state) => state.currentCurrency);
  const dispatch = useDispatch();

  const handleCurrencyChange = (e) => {
    dispatch(setCurrentCurrency(e.target.value));
  };

  return (
    <header>
      <h1>Header</h1>
      <select value={currentCurrency} onChange={handleCurrencyChange}>
        <option value="USD">USD</option>
        <option value="EUR">EUR</option>
        <option value="GBP">GBP</option>
      </select>
    </header>
  );
};

export default Header;
Enter fullscreen mode Exit fullscreen mode

Create another file called Footer.js and add the following code:

import React from "react";
import { useSelector, useDispatch } from "react-redux";
import { setCurrentCurrency } from "./actions";

const Footer = () => {
  const currentCurrency = useSelector((state) => state.currentCurrency);
  const dispatch = useDispatch();

  const handleCurrencyChange = (e) => {
    dispatch(setCurrentCurrency(e.target.value));
  };

  return (
    <footer>
      <h1>Footer</h1>
      <select value={currentCurrency} onChange={handleCurrencyChange}>
        <option value="USD">USD</option>
        <option value="EUR">EUR</option>
        <option value="GBP">GBP</option>
      </select>
    </footer>
  );
};

export default Footer;
Enter fullscreen mode Exit fullscreen mode

Finally, let's create the main App component to bring everything together.

In your main App.js file, add the following code:

import React from "react";
import { Provider } from "react-redux";
import Header from "./Header";
import Footer from "./Footer";
import store from "./store";

const App = () => {
  return (
    <Provider store={store}>
      <div className="App">
        <Header />
        <Footer />
      </div>
    </Provider>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

Using Redux Toolkit

Redux Toolkit is a package that provides a set of utilities to simplify common Redux use cases. It includes simplified ways to create reducers and action creators, as well as simplified ways to define initial state and store setup.

Let's see how to achieve the same result using Redux Toolkit.

Create a new file called store.js and add the following code:

import { configureStore } from "@reduxjs/toolkit";
import { currencyReducer } from "./reducers";

const store = configureStore({
  reducer: {
    currency: currencyReducer,
  },
});

export default store;
Enter fullscreen mode Exit fullscreen mode

Next, let's create the header and footer components that will display and update the current currency.

Create a new file called Header.js and add the following code:

import React from "react";
import { useSelector, useDispatch } from "react-redux";
import { setCurrentCurrency } from "./reducers";

const Header = () => {
  const currentCurrency = useSelector(
    (state) => state.currency.currentCurrency
  );
  const dispatch = useDispatch();

  const handleCurrencyChange = (e) => {
    dispatch(setCurrentCurrency(e.target.value));
  };

  return (
    <header>
      <h1>Header</h1>
      <select value={currentCurrency} onChange={handleCurrencyChange}>
        <option value="USD">USD</option>
        <option value="EUR">EUR</option>
        <option value="GBP">GBP</option>
      </select>
    </header>
  );
};

export default Header;
Enter fullscreen mode Exit fullscreen mode

Create another file called Footer.js and add the following code:

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

const Footer = () => {
  const currentCurrency = useSelector(
    (state) => state.currency.currentCurrency
  );
  const dispatch = useDispatch();

  const handleCurrencyChange = (e) => {
    dispatch(setCurrentCurrency(e.target.value));
  };

  return (
    <footer>
      <h1>Footer</h1>
      <select value={currentCurrency} onChange={handleCurrencyChange}>
        <option value="USD">USD</option>
        <option value="EUR">EUR</option>
        <option value="GBP">GBP</option>
      </select>
    </footer>
  );
};

export default Footer;
Enter fullscreen mode Exit fullscreen mode

Finally, let's create the main App component to bring everything together.

In your main App.js file, add the following code:

import React from "react";
import { Provider } from "react-redux";
import Header from "./Header";
import Footer from "./Footer";
import store from "./store";

const App = () => {
  return (
    <Provider store={store}>
      <div className="App">
        <Header />
        <Footer />
      </div>
    </Provider>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

Using React Atom

Now let's see how this can be achieved using React Atom.

Create a atoms.js file and add the following code:

import { atom } from "@mongez/react-atom";

export const currencyAtom = atom({
  key: "currency",
  default: "USD",
});
Enter fullscreen mode Exit fullscreen mode

Now let's create the header and footer components that will display and update the current currency.

Create a new file called Header.js and add the following code:

import React from "react";
import { currencyAtom } from "./atoms";

const Header = () => {
  const currentCurrency = currencyAtom.useValue();

  const handleCurrencyChange = (e) => {
    currencyAtom.update(e.target.value);
  };

  return (
    <header>
      <h1>Header</h1>
      <select value={currentCurrency} onChange={handleCurrencyChange}>
        <option value="USD">USD</option>
        <option value="EUR">EUR</option>
        <option value="GBP">GBP</option>
      </select>
    </header>
  );
};

export default Header;
Enter fullscreen mode Exit fullscreen mode

Create another file called Footer.js and add the following code:

import React from "react";
import { currencyAtom } from "./atoms";

const Footer = () => {
  const currentCurrency = currencyAtom.useValue();

  const handleCurrencyChange = (e) => {
    currencyAtom.update(e.target.value);
  };

  return (
    <footer>
      <h1>Footer</h1>
      <select value={currentCurrency} onChange={handleCurrencyChange}>
        <option value="USD">USD</option>
        <option value="EUR">EUR</option>
        <option value="GBP">GBP</option>
      </select>
    </footer>
  );
};

export default Footer;
Enter fullscreen mode Exit fullscreen mode

Finally, let's create the main App component to bring everything together.

In your main App.js file, add the following code:

import React from "react";

export default function App() {
  return (
    <div className="App">
      <Header />
      <Footer />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

And that's it! You've successfully implemented a global state management solution using React Atom.

In our next article, we'll go more deeply and see the other amazing features that React Atom provides.

You can see the entire series at mentoor.io

Top comments (0)