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.
- Features
- Installation
- Getting Started
- API Reference
- Examples
- Comparison with Other Libraries
- Contributing
- License
- Contact
- 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.
You can install Eoion via npm or yarn:
# Using npm
npm install eoion
# Using yarn
yarn add eoion
This section will guide you through the basics of using Eoion in your React projects.
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);
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);
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;
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,
});
Creates a persistent store that saves its state to localStorage
.
Syntax:
createPersistentStore(storeId, defaultStore, defaultMethods, validator);
Parameters:
-
storeId
(String): Unique identifier for the store inlocalStorage
. -
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: {},
});
Custom React hook to manage and subscribe to store state.
Syntax:
useStore(eoion, initialValue);
Parameters:
-
eoion
(Object): The object returned bystore.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");
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 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();
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);
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
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;
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;
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;
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 |
- 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.
- 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.
- 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.
- 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.
Contributions are welcome! Please check out the issues page to see what needs help.
This project is licensed under the MIT License - see the LICENSE file for details.
For more information or support, feel free to reach out:
- Email: ikorosamuel1@gmail.com
- Twitter: @DevBash1
Eoion - Lightweight state management made easy.