A React Global State that can persist data too!
Ajey N
Posted on June 20, 2024
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;
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;
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;
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');
Parameters:
-
key
(string): The key under which the value is stored in IndexedDB. -
defaultValue
(any): Initial value of the state. You can make thisundefined
when you need to read already stored data under thekey
. -
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;
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 };
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
!
Posted on June 20, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.