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 🙏

© 2026 – Pkg Stats / Ryan Hefner

pathdux

v1.2.9

Published

A simplified Redux state management solution with intelligent path-based updates and smart merging

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, and clear
  • ✅ 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 usePathdux hook 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 above

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

  1. Start with the basic Store.get() and Store.set() operations
  2. Add custom actions for complex business logic
  3. Use the usePathdux hook for cleaner functional components
  4. Explore path queries like [id=123] for dynamic data access

License: MIT