npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

eze-services

v0.9.3

Published

Eze-Services is a flexible, high-performance state management library for React applications. It provides modular state handling through hives, enabling scalable and efficient management of simple and complex state types like primitives, arrays, forms, an

Downloads

213

Readme

Beehive: A Flexible, Modular State Management Library

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.


Why Beehive?

  1. No More useState: Hives replace useState, 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.

  2. No More useEffect: Hives replace useEffect for handling side effects. You can subscribe to hives for real-time updates without the need to manually track dependencies or state changes.

  3. 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.

  4. 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.

  5. Persistent State: Beehive supports localStorage, sessionStorage, and memory storage using a simple storeKey option, allowing you to persist state across reloads.


Key Features

  • 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 with FormHive, 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.

Table of Contents


Getting Started

Install the library:

npm install eze-services

Creating Hives

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);

Rendering State with Bee

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);
});

Array State Management with ArrayBee and createHiveArray

1. Creating an Array Hive

createHiveArray creates a hive that manages an array of values and offers built-in methods for array manipulation.

Example: Creating an array hive

import { createHiveArray } from "eze-services";

// Initialize array hive
const itemArrayHive = createHiveArray([{ id: 1, name: "Item 1" }, { id: 2, name: "Item 2" }]);

2. Rendering Arrays with ArrayBee

ArrayBee maps over the array stored in a hive and renders each item.

Example: Rendering array items

import { ArrayBee } from "eze-services";

const ItemList = () => (
  <ArrayBee
    hive={itemArrayHive}
    Component={({ honey }) => (
      <div>
        <p>{honey.name}</p>
      </div>
    )}
  />
);

3. Array Hive API

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 its id.
  • updateById(id, newValue): Updates an item by its id.
  • removeByIndex(index): Removes an item at the given index.
  • updateByIndex(index, newValue): Updates an item at the given index.

Example: Manipulating an array hive

// 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" });

Proxy State Management with ProxyHive

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");

Observer Pattern with ObserverBee and createHiveObserver

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),
}));

Form State Management with FormBee, FormBees, and createFormHive

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.

1. Creating a Form Hive with createFormHive

createFormHive handles form state, validation, and submission logic.

Example: Creating a form hive

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"
});

2. Rendering Form Fields with FormBee

FormBee renders individual form fields and binds them to the form hive.

Example: Rendering a form field

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>
    )}
  />
);

3. Submitting Forms with onSubmit

The submit method revalidates the form and triggers the onSubmit callback.

Example: Submitting the form

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>
);

Props for createFormHive

createFormHive accepts several props that define how the form is structured, validated, and submitted:

  1. initialValue: Sets the initial values for the form fields.

    • Example: { username: "", email: "" }.
  2. storeKey (optional): Persist the form hive’s state in specified storage (e.g., localStorage).

  3. validator: Function that validates form fields. You can use libraries like Yup or Validator.js for more advanced validation.

  4. validateMode: Defines when to trigger validation: onBlur, onChange, or onSubmit.

  5. onSubmit: Callback triggered when the form is submitted successfully.


Validation Libraries: Integrating with Yup

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"
});

Persistent Storage and Store Keys

Persist state in localStorage, sessionStorage, or memory with storeKey.

const userHive = createHive({ name: "John" }, { storeKey: "user-data", storage: "localStorage" });

Custom Hooks with Components

useHoney Hook

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>
  );
};

useHive Hook

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>
  );
};

useFormHoney Hook

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>
  );
};

useFormHive Hook

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>
    );
};

Example: E-commerce Dashboard with Beehive

  • 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)
});

UserProfile Component


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>
);

ProductDetails Component


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>
    )}
  />
);

ToDoList Component


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>
);

OrderForm Component (using FormBee for independent form fields)

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;

Simplified Form Handling with Beehive and TextController

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.

Example: Using TextController for an Order Form

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.

TextController Component (General-purpose form input handler)

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>
      )}
    />
  );
}

Simplified Order Form using TextController


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>
);

How TextController Simplifies Form Management:

  1. Reusability: You can reuse the TextController across multiple forms, reducing redundancy and improving consistency.
  2. Clean Code: Instead of setting up each field manually, you simply pass the formHive, the field's id, and a label, and TextController handles the rest.
  3. Scalable: Adding new fields becomes incredibly easy — just call TextController with the new field details, and it’s ready to go.

Power of Beehive in Action:

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.


Why Choose Beehive Over Other Libraries?

1. Redux:

  • 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.

2. MobX:

  • 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.

3. Zustand:

  • 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, and ProxyHive to manage complex data without extra setup.

Why Beehive Is the Best Choice:

  1. Unified API: Manage all state types (primitives, arrays, forms, and nested objects) with one consistent API, eliminating the need for multiple tools or patterns.

  2. Real-Time Updates Without useEffect: Hives automatically trigger updates, so your components stay in sync with the latest data—no need for useEffect or manual dependency tracking.

  3. 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.

  4. Persistent State: Easily persist state across reloads using storeKey for local or session storage, with no extra setup.