DEV Community

Cover image for A React Global State that can persist data too!
Ajey N
Ajey N

Posted on

A React Global State that can persist data too!

In my previous article, I introduced a powerful yet simple hook called useDbState that lets you persist state in your React components just like useState. But wait, there's more!

Introducing useDbState 2.0.0

Hold on to your hats because useDbState just got an upgrade! Now, with useDbState 2.0.0, you can use the same state across multiple components without any extra boilerplate code or wrappers. Yep, you read that right—global state management made easy!

How Does useDbState Work?

Before diving into the new features, let's quickly recap how useDbState works. This custom React hook stores and retrieves state using IndexedDB, making your state persistent across page reloads. It's as easy to use as useState but with superpowers!

Basic Usage

Here's a quick example:

import React from 'react';
import { useDbState } from 'use-db-state';

const Counter = () => {
  const [count, setCount] = useDbState('count', 0);

  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
};

export default Counter;
Enter fullscreen mode Exit fullscreen mode

This code snippet stores the count state in IndexedDB under the key count, making it persistent across page reloads. Pretty cool, right?

New Features in useDbState 2.0.0

Global State Across Components

One of the standout features in the new version is the ability to share state across different components effortlessly. No more prop drilling or complex state management libraries. Just pure simplicity!

Example

Let's look at a practical example where we share user data across components:

Component A:

import React from 'react';
import { useDbState } from 'use-db-state';

const ComponentA = () => {
  const [user, setUser] = useDbState('user', { name: 'Alice', age: 25 });

  return (
    <div>
      <input
        type="text"
        value={user.name}
        onChange={(e) => setUser({ ...user, name: e.target.value })}
      />
      <input
        type="number"
        value={user.age}
        onChange={(e) => setUser({ ...user, age: parseInt(e.target.value) })}
      />
    </div>
  );
};

export default ComponentA;
Enter fullscreen mode Exit fullscreen mode

Component B:

import React from 'react';
import { useDbState } from 'use-db-state';

const ComponentB = () => {
  const [user] = useDbState('user');

  return (
    <div>
      <h1>{user?.name}</h1>
      <p>Age: {user?.age}</p>
    </div>
  );
};

export default ComponentB;
Enter fullscreen mode Exit fullscreen mode

In this example, ComponentA and ComponentB share the user state. Any updates in ComponentA will automatically reflect in ComponentB, and vice versa.

Observe in ComponentB the useDbState hook is passed with only the key and no initilization. This will let you access the data stored in IndexedDB under the key user

How It Works

useDbState leverages IndexedDB to store state data persistently. When initialized, it fetches the value from IndexedDB. If the value exists, it sets the state to the fetched value; otherwise, it uses the provided default value. It also subscribes to changes in the state associated with the key, ensuring all components using the same key are synchronized.

API

useDbState

const [value, setValue] = useDbState(key: string, defaultValue: any, dbName?: string = 'userDatabase', storeName?: string = 'userData');
Enter fullscreen mode Exit fullscreen mode

Parameters:

  • key (string): The key under which the value is stored in IndexedDB.
  • defaultValue (any): Initial value of the state. You can make this undefined when you need to read already stored data under the key.
  • dbName (string, optional): The name of the IndexedDB database. Defaults to 'userDatabase'.
  • storeName (string, optional): The name of the IndexedDB object store. Defaults to 'userData'.

Returns:

  • value (any): The current state value.
  • setValue (function): A function to update the state value.

More Practical Examples

Storing User Preferences

You can use useDbState to store user preferences like theme settings. You can change the theme from any component in your app and browser will remember what you set the next time you open your app:

import React from 'react';
import { useDbState } from 'use-db-state';

const ThemeToggle = () => {
  const [theme, setTheme] = useDbState('theme', 'light');

  return (
    <div>
      <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
        Toggle Theme
      </button>
      <p>Current theme: {theme}</p>
    </div>
  );
};

export default ThemeToggle;
Enter fullscreen mode Exit fullscreen mode

Managing a Shopping Cart

Easily manage a shopping cart across different components:

import React from 'react';
import { useDbState } from 'use-db-state';

const AddToCart = ({ item }) => {
  const [cart, setCart] = useDbState('cart', []);

  const addToCart = () => {
    setCart([...cart, item]);
  };

  return <button onClick={addToCart}>Add to Cart</button>;
};

const Cart = () => {
  const [cart] = useDbState('cart');

  return (
    <div>
      <h2>Shopping Cart</h2>
      <ul>
        {cart.map((item, index) => (
          <li key={index}>{item.name}</li>
        ))}
      </ul>
    </div>
  );
};

export { AddToCart, Cart };
Enter fullscreen mode Exit fullscreen mode

Conclusion

The useDbState hook could be a game-changer for your React state management. It simplifies persistence with IndexedDB and introduces a seamless way to share state across components without extra hassle. With these new features, managing global state in your React apps has never been easier.

So, go ahead and try out useDbState in your projects. Comment below if you find any interesting application or not-so-interesting bugs 😅. Would love to colloborate with you to make the hook better and more useful! 💪

Happy coding! 🚀


Feel free to reach out if you have any questions or need further assistance. You can find the full documentation on my GitHub repository.

If you found this article helpful, share it with your fellow developers and spread the word about use-db-state!

You can follow me on github and Linkedin

Top comments (0)