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

eoion

v1.0.3

Published

A versatile state management library that integrates seamlessly with React.

Downloads

192

Readme

npm version license downloads issues

Eoion is a lightweight, flexible, and easy-to-use state management library for React applications. It offers both simple and persistent state management solutions with minimal boilerplate, making it an excellent choice for developers seeking simplicity and efficiency.


Table of Contents


Features

  • Lightweight and Simple: Minimal setup and easy-to-understand API.
  • Flexible State Management: Supports both simple and persistent stores.
  • React Integration: Seamless integration with React through custom hooks.
  • Customizable: Allows custom validators and methods for enhanced control.
  • Reducer Support: Built-in support for reducers to manage complex state transitions.
  • Asynchronous Initial State: Supports asynchronous functions for initializing state.
  • TypeScript Support: Fully typed for better developer experience.
  • No External Dependencies: Pure JavaScript implementation without any external dependencies.

Installation

You can install Eoion via npm or yarn:

# Using npm
npm install eoion

# Using yarn
yarn add eoion

Getting Started

This section will guide you through the basics of using Eoion in your React projects.

Creating a Simple Store

import { createStore } from "eoion";

// Define the initial state
const defaultStore = {
    count: 0,
    user: {
        name: "John Doe",
        age: 30,
    },
};

// Create the store
const store = createStore(defaultStore);

Creating a Persistent Store

A persistent store saves its state to localStorage, allowing state persistence across browser sessions.

import { createPersistentStore } from "eoion";

// Define the initial state
const defaultStore = {
    theme: "light",
    language: "en",
};

// Create the persistent store with a unique ID
const persistentStore = createPersistentStore("appStore", defaultStore);

Using the useStore Hook

The useStore hook connects your React components to the store, providing real-time updates and state management.

import React from "react";
import { useStore } from "eoion";

// Assuming you have already created a store
const Counter = () => {
    const [count, setCount] = useStore(store.subscribe("count"));

    const increment = () => setCount(count + 1);
    const decrement = () => setCount(count - 1);

    return (
        <div>
            <h1>Count: {count}</h1>
            <button onClick={decrement}>-</button>
            <button onClick={increment}>+</button>
        </div>
    );
};

export default Counter;

API Reference

createStore

Creates a simple, non-persistent store.

Syntax:

createStore(defaultStore, defaultMethods, validator);

Parameters:

  • defaultStore (Object): The initial state of the store.
  • defaultMethods (Object, optional): Custom methods to manipulate the store state.
  • validator (Function, optional): A function to validate state changes.

Returns:
An object with the following methods:

  • subscribe(name)
  • reducer(state)
  • getState(name)
  • getStates()

Example:

const store = createStore({
    isAuthenticated: false,
    user: null,
});

createPersistentStore

Creates a persistent store that saves its state to localStorage.

Syntax:

createPersistentStore(storeId, defaultStore, defaultMethods, validator);

Parameters:

  • storeId (String): Unique identifier for the store in localStorage.
  • defaultStore (Object): The initial state of the store.
  • defaultMethods (Object, optional): Custom methods to manipulate the store state.
  • validator (Function, optional): A function to validate state changes.

Returns:
An object with the following methods:

  • subscribe(name)
  • reducer(state)
  • getState(name)
  • getStates()

Example:

const persistentStore = createPersistentStore("userStore", {
    token: null,
    preferences: {},
});

useStore

Custom React hook to manage and subscribe to store state.

Syntax:

useStore(eoion, initialValue);

Parameters:

  • eoion (Object): The object returned by store.subscribe(name).
  • initialValue (*, optional): Overrides the store's default value for the subscribed state.

Returns:
An array [state, setState].

Example:

const [theme, setTheme] = useStore(persistentStore.subscribe("theme"), "dark");

Store Methods

When you subscribe to a state, you get access to several methods:

  • storeId: The unique identifier of the store.
  • store: The entire store object.
  • onChange(state, value): Manually trigger a state change.
  • getState(name): Get the current value of a specific state.
  • getStates(): Get the current values of all states.
  • on(name, callback): Add a listener for a specific state update event.
  • off(name, callback): Remove a listener for a specific state update event.

Example:

const eoion = store.subscribe("user");

eoion.on("store-UPDATE-user", (newUser) => {
    console.log("User updated:", newUser);
});

Reducers

Reducers allow you to manage complex state transitions.

Setting a Reducer:

store.reducer("count").set((state, action) => {
    switch (action.type) {
        case "INCREMENT":
            return state + 1;
        case "DECREMENT":
            return state - 1;
        default:
            return state;
    }
});

**

Dispatching Actions:**

store.reducer("count").dispatch({ type: "INCREMENT" });

Subscribing to Reducer Updates:

const unsubscribe = store.reducer("count").subscribe((newCount) => {
    console.log("Count updated:", newCount);
});

// To unsubscribe
unsubscribe();

Custom Validators

Validators allow you to enforce rules on state changes.

Example:

const validator = (stateName, stateValue) => {
    if (stateName === "age" && (stateValue < 0 || stateValue > 120)) {
        console.error("Invalid age value!");
        return false;
    }
    return true;
};

const store = createStore({ age: 25 }, {}, validator);

Custom Methods

You can define custom methods to manipulate state in a controlled manner.

Defining Custom Methods:

const methods = {
    increment: (value, amount = 1) => value + amount,
    decrement: (value, amount = 1) => value - amount,
};

const store = createStore({ count: 0 }, methods);

const counter = store.subscribe("count");

counter.increment(); // Increments count by 1
counter.decrement(2); // Decrements count by 2

Examples

Counter Example

Store Setup:

import { createStore } from "eoion";

const methods = {
    increment: (value) => value + 1,
    decrement: (value) => value - 1,
};

const store = createStore({ count: 0 }, methods);

React Component:

import React from "react";
import { useStore } from "eoion";

const Counter = () => {
    const [count, setCount] = useStore(store.subscribe("count"));

    const increment = () => setCount(store.increment);
    const decrement = () => setCount(store.decrement);

    return (
        <div>
            <h1>Count: {count}</h1>
            <button onClick={decrement}>-</button>
            <button onClick={increment}>+</button>
        </div>
    );
};

export default Counter;

Theme Toggler Example

Persistent Store Setup:

import { createPersistentStore } from "eoion";

const store = createPersistentStore("themeStore", { theme: "light" });

store.reducer("theme").set((state) => (state === "light" ? "dark" : "light"));

React Component:

import React from "react";
import { useStore } from "eoion";

const ThemeToggler = () => {
    const [theme, toggleTheme] = useStore(store.subscribe("theme"));

    return (
        <div>
            <h1>Current Theme: {theme}</h1>
            <button onClick={toggleTheme}>Toggle Theme</button>
        </div>
    );
};

export default ThemeToggler;

Asynchronous Initial State Example

Persistent Store Setup with Async Initialization:

import { createPersistentStore } from "eoion";

const defaultStore = {
    user: async () => {
        // Simulate async data fetching
        const response = await fetch("/api/user");
        const data = await response.json();
        return data;
    },
};

const store = createPersistentStore("userStore", defaultStore);

React Component:

import React, { useEffect, useState } from "react";
import { useStore } from "eoion";

const UserProfile = () => {
    const [user, setUser] = useStore(store.subscribe("user"));

    useEffect(() => {
        const unsubscribe = store.reducer("user").subscribe((state) => {
            console.log({ state });
        });

        return () => unsubscribe();
    }, []);

    if (!user) return <div>Loading...</div>;

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

export default UserProfile;

Comparison with Other Libraries

| Feature | Eoion | Redux | Zustand | Recoil | | --------------------- | ----------------- | ------------------------- | ----------------- | ------------------------ | | Ease of Use | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | | Boilerplate | Minimal | High | Minimal | Moderate | | Bundle Size | Very Small | Moderate | Very Small | Moderate | | React Integration | Seamless | Requires Additional Setup | Seamless | Seamless | | State Structure | Flexible | Centralized Store | Flexible | Atom-based | | Async State | Simple with Hooks | Complex (Thunk/Saga) | Simple with Hooks | Built-in Async Selectors | | Community Support | Growing | Large | Growing | Growing |

Eoion vs. Redux

  • Learning Curve: Eoion is much easier to learn and use compared to Redux, which requires understanding concepts like actions, reducers, and middleware.
  • Boilerplate: Eoion is much simpler to set up and requires significantly less boilerplate than Redux, making it easier for developers to start using it in their projects.
  • State Persistence: Eoion offers built-in persistent state management without the need for external libraries.

Eoion vs. Context API

  • Ease of Use: Eoion provides a more straightforward and structured approach to state management compared to the Context API, which can become complex in large applications.
  • Reusability: Eoion’s store methods and custom hooks enhance reusability and separation of concerns.
  • Performance: Eoion’s subscription model can offer better performance in large applications by minimizing unnecessary re-renders.

Eoion vs. Zustand

  • Simplicity: Eoion focuses on simplicity and ease of use, similar to Zustand, but with built-in support for reducers and state persistence.
  • API Structure: Eoion provides a more structured API, making it easier to manage complex state and reducers.
  • State Management: Both Eoion and Zustand offer flexible state management, but Eoion provides a more React-centric API with its useStore hook.

Eoion vs. Recoil

  • Learning Curve: Eoion is easier to learn and use compared to Recoil, which has a steeper learning curve due to its more complex API.
  • Flexibility: Eoion provides flexibility with custom validators and methods, while Recoil is more opinionated in its approach to state management.
  • State Persistence: Eoion offers state persistence out-of-the-box, whereas Recoil requires additional setup or third-party libraries for persistence.
  • State Structure: Eoion offers a flexible state structure without the need for atoms and selectors, unlike Recoil, which uses these concepts heavily.
  • Async State Management: Recoil has built-in async selectors, whereas Eoion keeps async management simple with React hooks.

Contributing

Contributions are welcome! Please check out the issues page to see what needs help.


License

This project is licensed under the MIT License - see the LICENSE file for details.


Contact

For more information or support, feel free to reach out:


Eoion - Lightweight state management made easy.