pathdux
v1.2.9
Published
A simplified Redux state management solution with intelligent path-based updates and smart merging
Maintainers
Readme
Pathdux ⚡
Simple and powerful global state for React with intuitive path-based syntax
Pathdux is a lightweight state management library for React that combines the simplicity of local state with the power of global state, using an intuitive path-based syntax to access and modify data anywhere in your application.
🚀 Key Features
- ✅ Simple syntax - Access state with paths like
"user.profile.name" - ✅ Intuitive operations -
set,get,remove,push, andclear - ✅ Immutable updates - All operations are side-effect free
- ✅ Flexible typing - Supports objects, arrays, and primitive values
- ✅ Zero configuration - Ready to use immediately
- ✅ Smart merging - Objects are merged by default, arrays replaced
- ✅ React hooks support - Includes
usePathduxhook for easy access
📦 Installation
npm install pathdux⚡ Quick Start
1. Wrap Your App
import { PathduxProvider } from 'pathdux';
const initialState = {
user: { name: "Ana", age: 28 },
todos: [
{ id: 1, text: "Learn Pathdux", completed: false }
]
};
// Customize your actions (optional)
const initialActions = ({ Store }) => ({
getUser: () => Store.get("user"),
addTodo: (text) => Store.push("todos[]", {
id: Date.now(),
text,
completed: false
})
});
function App() {
return (
<PathduxProvider
initialState={initialState}
initialActions={initialActions}
>
<TodoApp />
</PathduxProvider>
);
}2. Use in Components
Option A: Props Injection (Recommended for Class Components)
function TodoApp({ Store, Action }) {
// Get values from state
const user = Store.get("user");
const todos = Store.get("todos");
const currentUser = Action.getUser();
const toggleTheme = () => {
const currentTheme = Store.get("app.theme");
Store.set("app.theme", currentTheme === 'dark' ? 'light' : 'dark');
};
return (
<div>
<h1>Hello, {user.name}!</h1>
<button onClick={toggleTheme}>
Toggle theme
</button>
</div>
);
}Option B: usePathdux Hook (Recommended for Functional Components)
import { usePathdux } from 'pathdux';
function TodoApp() {
const { Store, Action } = usePathdux();
const user = Store.get("user");
const todos = Store.get("todos");
const addNewTodo = () => {
Action.addTodo("New todo from hook");
};
return (
<div>
<h1>Welcome, {user.name}!</h1>
<button onClick={addNewTodo}>
Add Todo
</button>
</div>
);
}🛠 Complete API
Store.get(path?, defaultValue?)
Gets a value from global state.
// Complete state
const fullState = Store.get();
// Specific value
const userName = Store.get("user.name");
// With default value
const theme = Store.get("app.theme", "light");
// Array element by index
const firstTodo = Store.get("todos[0]");
// Array element by query
const todo = Store.get("todos[id=123]");Store.set(path, value, options?)
Sets a value in the state. Objects are merged by default unless noMerge: true is specified.
// Simple value
Store.set("user.age", 29);
// Nested object (smart merge by default)
Store.set("user.profile", { theme: "dark" });
// user.profile keeps existing properties and adds theme
// With options (noMerge prevents object merging)
Store.set("user.profile", { premium: true }, { noMerge: true });
// Array element
Store.set("todos[0].completed", true);Store.push(path, value)
Adds elements to an array.
// Add single element
Store.push("todos", { id: 2, text: "New task" });
// Add multiple elements
Store.push("todos", [task1, task2, task3]);
// Shorthand syntax for arrays
Store.push("todos[]", newTask); // Equivalent to aboveStore.remove(path)
Removes properties or array elements.
// Remove property from object
Store.remove("user.token");
// Remove from array by index
Store.remove("todos[0]");
// Remove by condition
Store.remove("todos[id=2]");
// Remove nested property
Store.remove("user.profile.theme");Store.clear(path)
Clears arrays or objects.
// Empty array
Store.clear("todos");
// Empty object
Store.clear("user.preferences");
// Reset to default structure
Store.clear("app.settings");🎯 Practical Examples
User Management System
function UserProfile({ Store }) {
const user = Store.get("user");
const updateProfile = (updates) => {
// Smart merge: keeps existing properties
Store.set("user.profile", updates);
};
const addContact = (type, value) => {
Store.push("user.contacts[]", { type, value, verified: false });
};
const removeContact = (index) => {
Store.remove(`user.contacts[${index}]`);
};
const resetSettings = () => {
Store.clear("user.settings");
};
return (
<div>
<h2>{user.name}</h2>
<button onClick={() => updateProfile({ theme: "dark" })}>
Set Dark Theme
</button>
</div>
);
}Todo Application
function TodoApp({ Store }) {
const todos = Store.get("todos") || [];
const addTodo = (text) => {
Store.push("todos[]", {
id: Date.now(),
text,
completed: false,
createdAt: new Date().toISOString()
});
};
const toggleTodo = (id) => {
const completed = Store.get(`todos[id=${id}].completed`);
Store.set(`todos[id=${id}].completed`, !completed);
};
const updateTodoText = (id, text) => {
Store.set(`todos[id=${id}].text`, text);
};
const clearCompleted = () => {
const completedIds = todos
.filter(todo => todo.completed)
.map(todo => todo.id);
completedIds.forEach(id => {
Store.remove(`todos[id=${id}]`);
});
};
return (
<div>
{todos.map(todo => (
<div key={todo.id}>
<input
type="checkbox"
checked={todo.completed}
onChange={() => toggleTodo(todo.id)}
/>
<span>{todo.text}</span>
</div>
))}
</div>
);
}🔧 Advanced Configuration
Custom Actions with Business Logic
const initialActions = ({ Store }) => ({
// User management
login: (email, password) => {
// Simulate API call
Store.set("user.isLoading", true);
setTimeout(() => {
Store.set("user", {
email,
name: email.split('@')[0],
isLoggedIn: true,
lastLogin: new Date().toISOString()
});
Store.set("user.isLoading", false);
}, 500);
},
logout: () => {
Store.remove("user.authToken");
Store.set("user.isLoggedIn", false);
Store.clear("user.session");
},
// Todo management
addTodo: (text) => {
const newTodo = {
id: Date.now(),
text,
completed: false,
createdAt: new Date().toISOString(),
priority: "medium"
};
Store.push("todos", newTodo);
},
// Bulk operations
markAllAsComplete: () => {
const todos = Store.get("todos") || [];
todos.forEach((todo, index) => {
Store.set(`todos[${index}].completed`, true);
});
},
// Complex state transformations
resetApp: () => {
Store.clear("todos");
Store.set("user.preferences", {});
Store.set("app.theme", "light");
Store.set("app.notifications", []);
}
});Using usePathdux Hook in Deeply Nested Components
import { usePathdux } from 'pathdux';
function DeeplyNestedComponent() {
const { Store, Action } = usePathdux();
// Access state anywhere
const theme = Store.get("app.theme");
// Use custom actions
const handleLogin = () => {
Action.login("[email protected]", "password123");
};
return (
<div className={`theme-${theme}`}>
<button onClick={handleLogin}>Login</button>
</div>
);
}📝 Path Syntax Guide
| Example | Description | Use Case |
|---------|-------------|----------|
| "user.name" | Nested property | Store.get("user.name") |
| "todos[0]" | Array by index | Store.set("todos[0].done", true) |
| "todos[id=123]" | Array by query | Store.remove("todos[id=123]") |
| "todos[]" | Array shorthand | Store.push("todos[]", item) |
| "data.items[1].value" | Complex nested | Store.get("data.items[1].value") |
🔄 Smart Merging Behavior
Pathdux intelligently merges objects by default:
// Initial state
{ user: { name: "John", age: 30, email: "[email protected]" } }
// Update with merge (default)
Store.set("user", { age: 31, city: "NYC" });
// Result: { user: { name: "John", age: 31, email: "[email protected]", city: "NYC" } }
// Update without merge
Store.set("user", { age: 31 }, { noMerge: true });
// Result: { user: { age: 31 } } // Other properties removed🎯 When to Use Pathdux
Great for:
- Complex, nested state structures
- Rapid prototyping and development
- Applications with dynamic forms
- Configuration panels and dashboards
- When you want global state without Redux boilerplate
Consider alternatives for:
- Very simple state (use
useState)
🚀 Next Steps
- Start with the basic
Store.get()andStore.set()operations - Add custom actions for complex business logic
- Use the
usePathduxhook for cleaner functional components - Explore path queries like
[id=123]for dynamic data access
License: MIT
