Beehive is a high-performance, flexible, and easy-to-use state management library for React applications. It simplifies managing state across both small and large projects without the need for a centralized store.
-
No More
useState
: Hives replaceuseState
, allowing you to manage state outside of components. Whether you're managing simple or complex state,createHive
ensures consistent, centralized state management across your app. -
No More
useEffect
: Hives replaceuseEffect
for handling side effects. You can subscribe to hives for real-time updates without the need to manually track dependencies or state changes. -
Unified State Pattern: Beehive offers a single API for managing primitives, arrays, forms, and deeply nested objects, reducing the need for multiple patterns across your project.
-
Modular and Scalable: Hives are modular, meaning they can be used independently or in combination. This allows you to scale state management from small components to large, complex applications without added overhead.
-
Persistent State: Beehive supports localStorage, sessionStorage, and memory storage using a simple
storeKey
option, allowing you to persist state across reloads.
- Hives: Manage state in a modular way with
createHive
, allowing flexible control over any type of state (primitives, arrays, nested objects). - Array and Form Handling: Built-in support for managing arrays with
ArrayHive
and forms withFormHive
, providing validation out of the box. - Subscriptions: Components automatically update when hive state changes, ensuring real-time updates without manual re-renders.
- ProxyHive: Manage deeply nested objects efficiently and update individual fields without rebuilding the entire object.
- Beehive: A Flexible, Modular State Management Library
- Why Beehive?
- Key Features
- Table of Contents
- Getting Started
- Creating Hives
- Rendering State with Bee
- Array State Management with ArrayBee and createHiveArray
- Proxy State Management with ProxyHive
- Observer Pattern with ObserverBee and createHiveObserver
- Form State Management with FormBee, FormBees, and createFormHive
- Persistent Storage and Store Keys
- Custom Hooks with Components
- Example: E-commerce Dashboard with Beehive
- Simplified Form Handling with Beehive and
TextController
- Why Choose Beehive Over Other Libraries?
Install the library:
npm install eze-services
Hives manage individual pieces of state in a modular way. You can easily subscribe to state changes with subscribe()
.
import { createHive } from 'eze-services';
// Primitive state hive
const countHive = createHive(0);
// Subscribing to changes
countHive.subscribe((newCount) => console.log("Count updated:", newCount));
// Update state
countHive.setHoney(1);
Bee
connects the state in a hive to your component. You can also subscribe to state changes using the subscribe()
method, making it easy to track and act on updates.
import { Bee } from 'eze-services';
const Counter = () => (
<Bee hive={countHive} Component={({ honey, setHoney }) => (
<div>
<p>{honey}</p>
<button onClick={() => setHoney(honey + 1)}>Increment</button>
</div>
)}/>
);
// Subscribing outside of React
countHive.subscribe((newCount) => {
console.log('Count changed to:', newCount);
});
createHiveArray
creates a hive that manages an array of values and offers built-in methods for array manipulation.
import { createHiveArray } from "eze-services";
// Initialize array hive
const itemArrayHive = createHiveArray([{ id: 1, name: "Item 1" }, { id: 2, name: "Item 2" }]);
ArrayBee
maps over the array stored in a hive and renders each item.
import { ArrayBee } from "eze-services";
const ItemList = () => (
<ArrayBee
hive={itemArrayHive}
Component={({ honey }) => (
<div>
<p>{honey.name}</p>
</div>
)}
/>
);
The createHiveArray
provides utility methods for array operations:
push(newItem)
: Adds a new item to the end of the array.pop()
: Removes the last item from the array.shift()
: Removes the first item from the array.unshift(newItem)
: Adds a new item to the beginning of the array.splice(start, deleteCount, ...newItems)
: Removes items from the array and/or adds new items.removeById(id)
: Removes an item from the array based on itsid
.updateById(id, newValue)
: Updates an item by itsid
.removeByIndex(index)
: Removes an item at the given index.updateByIndex(index, newValue)
: Updates an item at the given index.
// Push a new item
itemArrayHive.push({ id: 3, name: "Item 3" });
// Remove the first item
itemArrayHive.shift();
// Update an item by its index
itemArrayHive.updateByIndex(0, { id: 2, name: "Updated Item 2" });
Manage deeply nested state objects and subscribe to changes within nested properties.
import { createProxyHive } from 'eze-services';
const userProxyHive = createProxyHive({ name: "John", address: { city: "New York" } });
const cityHive = userProxyHive.getNestedHive("address").getNestedHive("city");
cityHive.setHoney("San Francisco");
Listen to changes across multiple hives using ObserverBee
or createHiveObserver
.
import { createHiveObserver, ObserverBee } from 'eze-services';
const observerHive = createHiveObserver((observe) => ({
userName: observe(userProxyHive),
itemCount: observe(itemArrayHive),
}));
createFormHive
manages form state and validation. It provides tools for easy form handling, validation, and submission. Forms are rendered with FormBee
for individual fields or FormBees
for handling multiple fields.
createFormHive
handles form state, validation, and submission logic.
import { createFormHive } from "eze-services";
const formHive = createFormHive({
initialValue: { username: "", email: "" },
validator: (key, value) => {
if (key === "username" && value.length < 3) return "Username must be at least 3 characters";
if (key === "email" && !value.includes("@")) return "Invalid email address";
return null;
},
onSubmit: (honey) => {
console.log("Form Submitted", honey);
},
validateMode: "onBlur" // Other options: "onChange", "onSubmit"
});
FormBee
renders individual form fields and binds them to the form hive.
import { FormBee } from "eze-services";
const UsernameField = () => (
<FormBee
hive={formHive.getNestedHive("username")}
Component={({ honey, error, setHoney, validate }) => (
<div>
<input
type="text"
value={honey}
onChange={(e) => setHoney(e.target.value)}
onBlur={() => validate(honey)} // Trigger validation on blur
/>
{error && <span>{error}</span>}
</div>
)}
/>
);
The submit
method revalidates the form and triggers the onSubmit
callback.
const handleSubmit = (e) => {
formHive.submit(e); // Revalidates and submits the form
};
return (
<form onSubmit={handleSubmit}>
<FormBee hive={formHive.getNestedHive("username")} Component={UsernameField} />
<button type="submit">Submit</button>
</form>
);
createFormHive
accepts several props that define how the form is structured, validated, and submitted:
-
initialValue
: Sets the initial values for the form fields.- Example:
{ username: "", email: "" }
.
- Example:
-
storeKey
(optional): Persist the form hive’s state in specified storage (e.g.,localStorage
). -
validator
: Function that validates form fields. You can use libraries like Yup or Validator.js for more advanced validation. -
validateMode
: Defines when to trigger validation:onBlur
,onChange
, oronSubmit
. -
onSubmit
: Callback triggered when the form is submitted successfully.
You can integrate Yup for more complex validation. Here’s an example of using Yup with createFormHive
:
import * as Yup from "yup";
import { createFormHive } from "eze-services";
const formSchema = Yup.object().shape({
username: Yup.string().min(3, "Username must be at least 3 characters").required("Username is required"),
email: Yup.string().email("Invalid email").required("Email is required")
});
const formHive = createFormHive({
initialValue: { username: "", email: "" },
validator: async (key, value) => {
try {
await formSchema.validateAt(key, { [key]: value });
return null;
} catch (err) {
return err.message;
}
},
onSubmit: (honey) => {
console.log("Form Submitted", honey);
},
validateMode: "onBlur"
});
Persist state in localStorage
, sessionStorage
, or memory with storeKey
.
const userHive = createHive({ name: "John" }, { storeKey: "user-data", storage: "localStorage" });
Returns the current state from a hive and updates the component when the hive’s state changes.
import { useHoney } from 'eze-services';
const Counter = () => {
const honey = useHoney(countHive);
return (
<div>
<p>{honey}</p>
<button onClick={() => countHive.setHoney(honey + 1)}>Increment</button>
</div>
);
};
Returns the state and a function to update the state from a hive.
import { useHive } from 'eze-services';
const Counter = () => {
const [honey, setHoney] = useHive(countHive);
return (
<div>
<p>{honey}</p>
<button onClick={() => setHoney(honey + 1)}>Increment</button>
</div>
);
};
Works with form hives to get the value and error state.
import { useFormHoney } from 'eze-services';
const UsernameField = () => {
const { value, error } = useFormHoney(formHive.getNestedHive("username"));
return (
<div>
<input type="text" value={value} onChange={(e) => formHive.setNestedHoney("username", e.target.value)} />
{error && <span>{error}</span>}
</div>
);
};
Similar to useHive
but designed for form hives. It provides the validate
method to trigger validation.
import { useFormHive } from 'eze-services';
const UsernameField = () => {
const [honey, validate] = useFormHive(formHive.getNestedHive("username"));
return (
<div>
<input type="text" value={honey.value} onChange={(e) => validate(e.target.value)} />
{honey.error && <span>{honey.error}</span>}
</div>
);
};
- User Profile (using ProxyHive for nested details),
- To-Do List (using ArrayHive and ArrayBee),
- Product Details (using Hive for simple product data),
- Order Creation Form (using FormHive and FormBee for handling independent form fields).
import { createHive, createHiveArray, createProxyHive, createFormHive, ArrayBee, FormBee, Bee } from 'eze-services';
// ProxyHive for User Profile
const userProfileHive = createProxyHive({
personalInfo: { name: 'John Doe', email: '[email protected]' },
preferences: { notifications: true, theme: 'dark' }
});
// Hive for Product Details
const productDetailsHive = createHive({ name: 'Task Manager', version: '1.0', activeUsers: 500 });
// ArrayHive for To-Do List
const todoListHive = createHiveArray([{ id: 1, task: 'Complete the report', completed: false }]);
// FormHive for Order Creation
const orderFormHive = createFormHive({
initialValue: { productName: '', quantity: 1, address: '' },
validator: (key, value) => (!value ? 'This field is required' : ''),
onSubmit: (honey) => console.log('Order Submitted:', honey)
});
const UserProfile = () => (
<div>
<h2>User Profile</h2>
<Bee
hive={userProfileHive.getNestedHive("userProfile")}
Component={({ honey, setHoney }) => (
<div>
<p>Name: {honey.name}</p>
<p>Email: {honey.email}</p>
</div>
)}
/>
<Bee
hive={userProfileHive.getNestedHive("preferences")}
Component={({ honey, setHoney }) => (
<div>
<p>Notifications: {honey.notifications ? "Enabled" : "Disabled"}</p>
<p>Theme: {honey.theme}</p>
<button onClick={() => setHoney((prev) => ({ ...prev, theme: prev.preferences.theme === "dark" ? "light" : "dark" }))}>Toggle Theme</button>
</div>
)}
/>
</div>
);
const ProductDetails = () => (
<Bee
hive={productDetailsHive}
Component={({ honey, setHoney }) => (
<div>
<h2>Product Details</h2>
<p>Product Name: {honey.name}</p>
<p>Version: {honey.version}</p>
<p>Active Users: {honey.activeUsers}</p>
<button onClick={() => setHoney(prev => ({ ...prev, activeUsers: prev.activeUsers + 1 }))}>
Increment Active Users
</button>
</div>
)}
/>
);
const TodoList = () => (
<div>
<h2>To-Do List</h2>
<ArrayBee
hive={todoListHive}
Component={({ honey, setHoney }) => (
<div key={honey.id}>
<p>{honey.task} {honey.completed ? '(Completed)' : ''}</p>
<button onClick={() => setHoney(prev => ({ ...prev, completed: !prev.completed }))}>
Toggle Complete
</button>
</div>
)}
/>
<button onClick={() => todoListHive.push({ id: Date.now(), task: 'New Task', completed: false })}>
Add New Task
</button>
</div>
);
const OrderForm = () => (
<form
onSubmit={orderFormHive.submit}>
<h2>Create Order</h2>
<FormBee
hive={orderFormHive.getNestedHive("productName")}
Component={({ honey, error, validate }) => (
<div>
<label>Product Name:</label>
<input type="text" value={honey} onChange={(e) => validate(e.target.value)} />
{error && <span>{error}</span>}
</div>
)}
/>
<FormBee
hive={orderFormHive.getNestedHive("quantity")}
Component={({ honey, error, validate }) => (
<div>
<label>Quantity:</label>
<input type="text" value={honey} onChange={(e) => validate(e.target.value)} />
{error && <span>{error}</span>}
</div>
)}
/>
<FormBee
hive={orderFormHive.getNestedHive("address")}
Component={({ honey, error, validate }) => (
<div>
<label>Address:</label>
<input type="text" value={honey} onChange={(e) => validate(e.target.value)} />
{error && <span>{error}</span>}
</div>
)}
/>
<button type="submit">Submit Order</button>
</form>
);
// Main Dashboard Component
const Dashboard = () => (
<div>
<UserProfile />
<ProductDetails />
<TodoList />
<OrderForm />
</div>
);
export default Dashboard;
With Beehive, managing state for forms is straightforward and scalable. Here's a powerful yet easy-to-use way to handle form fields using the TextController
component.
The TextController is a general-purpose form input handler that allows you to manage form fields with minimal setup. This makes working with complex forms in Beehive seamless, providing you with an easy way to handle field states, validation, and updates.
In this example, the TextController
helps simplify the creation of form fields by taking a formHive
, the id
of the field, and a title
for the input label. Instead of manually setting up each form field, you can simply use the TextController
to handle everything.
interface ControllerElementProps<T> extends LabeledProps {
hive: IFormHive<T>;
id: keyof T;
title: string;
}
function TextController<T>({ formHive, id, title }: ControllerElementProps) {
return (
<FormBee
hive={formHive.getNestedHive(id)}
Component={({ honey, error, validate }) => (
<div>
<label>{title}:</label>
<input type="text" value={honey} onChange={(e) => validate(e.target.value)} />
{error && <span>{error}</span>}
</div>
)}
/>
);
}
const SimplifiedOrderForm = () => (
<form onSubmit={(e) => { e.preventDefault(); orderFormHive.submit(); }}>
<h2>Create Order (With TextController)</h2>
{/* Reusable TextController for each field */}
<TextController formHive={orderFormHive} id="productName" title="Product Name" />
<TextController formHive={orderFormHive} id="address" title="Address" />
<TextController formHive={orderFormHive} id="quantity" title="Quantity" />
<button type="submit">Submit Order</button>
</form>
);
- Reusability: You can reuse the
TextController
across multiple forms, reducing redundancy and improving consistency. - Clean Code: Instead of setting up each field manually, you simply pass the
formHive
, the field'sid
, and a label, andTextController
handles the rest. - Scalable: Adding new fields becomes incredibly easy — just call
TextController
with the new field details, and it’s ready to go.
With Beehive, you're managing form fields in a modular and scalable way, without the boilerplate code commonly seen in other state management solutions. The TextController is a clear example of how Beehive simplifies development, giving you an easy-to-use interface while maintaining the flexibility to scale and customize as your app grows.
- More Efficient State Management: Redux requires centralized stores, actions, and reducers, which adds boilerplate and complexity. Beehive eliminates this with modular hives, allowing you to manage each piece of state independently, without extra code.
- Why It's Better: Beehive reduces the need for complex configurations and keeps state modular, making it easier to debug and scale.
- Cleaner, Simpler API: MobX uses observables and decorators, which can add complexity. Beehive offers a functional, easy-to-use API that handles state without complex syntax. Hives provide built-in solutions for arrays and forms.
- Why It's Better: Beehive keeps development intuitive and clean, with fewer moving parts and a simpler learning curve.
- More Structure for Larger Projects: Zustand is minimal, but it lacks the structure needed for managing complex states like forms, arrays, or deeply nested objects. Beehive provides built-in support for these cases, offering more structure for larger, complex apps.
- Why It's Better: For larger or more advanced apps, Beehive scales better by providing tools like
ArrayHive
,FormHive
, andProxyHive
to manage complex data without extra setup.
-
Unified API: Manage all state types (primitives, arrays, forms, and nested objects) with one consistent API, eliminating the need for multiple tools or patterns.
-
Real-Time Updates Without
useEffect
: Hives automatically trigger updates, so your components stay in sync with the latest data—no need foruseEffect
or manual dependency tracking. -
Scalable and Modular: Hives scale easily from small components to large apps. Each module can manage its own state, keeping the project modular and organized.
-
Persistent State: Easily persist state across reloads using
storeKey
for local or session storage, with no extra setup.