Nucleux: A Fresh Approach to State Management in React Applications

State management remains one of the most discussed challenges in modern web development. As our applications grow in complexity, managing state across components becomes increasingly difficult. While there are numerous solutions on the market—Redux, Zustand, Recoil, Jotai—many developers still find themselves caught between excessive boilerplate and limited functionality.
Today, I'm excited to introduce Nucleux, a state management library that focuses on simplicity without sacrificing power.
The Evolution of State Management
The journey to better state management has been ongoing since React's early days. We've moved from prop drilling to Context API to more sophisticated solutions like Redux. Each iteration has aimed to solve specific problems:
Prop drilling became unwieldy as apps grew
Context API introduced performance challenges
Redux offered structure but at the cost of verbosity
Newer libraries simplified APIs but often lacked advanced features
Nucleux represents the next step in this evolution, building on what I learned from developing App's Digest (its predecessor) and incorporating feedback from real-world usage.
Introducing Nucleux
Nucleux is a state management library based on two powerful software patterns:
Publisher-subscriber pattern - For efficient state updates
Inversion of Control (IoC) container - For organized store management
But what makes it special is how these patterns translate into a developer-friendly experience:
// This simple code is all you need to create and use state
import { Store, useStore, useValue } from 'nucleux';
class CounterStore extends Store {
count = this.atom(0);
increment() {
this.count.value += 1;
}
}
function Counter() {
const counterStore = useStore(CounterStore);
const count = useValue(counterStore.count);
return (
<button onClick={() => counterStore.increment()}>
Count: {count}
</button>
);
}
The code above showcases Nucleux's philosophy: state management shouldn't require excessive boilerplate or complex patterns.
Key Features That Make Nucleux Stand Out
1. Atomic Updates
Unlike global state solutions where updating one property can trigger unnecessary re-renders, Nucleux only updates components that are subscribed to specific atoms:
// Only components using counterStore.count will update
counterStore.count.value += 1;
// Other atoms remain untouched
counterStore.name.value = "New name"; // Independent update
2. No Provider Hell
We've all been there—wrapping our application in multiple nested providers:
// The old way with provider hell
<ThemeProvider>
<AuthProvider>
<CartProvider>
<SettingsProvider>
<App />
</SettingsProvider>
</CartProvider>
</AuthProvider>
</ThemeProvider>
With Nucleux, this is completely eliminated. The IoC container manages store instances behind the scenes:
// The Nucleux way - no providers needed
<App />
3. Automatic Dependency Injection
Need one store to access another? Nucleux handles it elegantly:
class UserStore extends Store {
currentUser = this.atom(null);
}
class CartStore extends Store {
userStore = this.inject(UserStore); // Inject the UserStore
items = this.atom([]);
checkout() {
if (!this.userStore.currentUser.value) {
throw new Error("User must be logged in");
}
// Process checkout...
}
}
Building a Todo App with Nucleux
Let's see how these concepts translate to a real-world example by building a Todo app.
1. Create a Todo Store
// TodoStore.js
import { Store } from 'nucleux';
import { nanoid } from 'nanoid';
class TodoStore extends Store {
// Create an atom to store todos with persistence
todos = this.atom([], 'todos-storage');
addTodo(text) {
this.todos.value = [
...this.todos.value,
{
id: nanoid(),
text,
completed: false,
createdAt: Date.now()
}
];
}
toggleTodo(id) {
this.todos.value = this.todos.value.map(todo =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
);
}
updateTodo(id, text) {
this.todos.value = this.todos.value.map(todo =>
todo.id === id ? { ...todo, text } : todo
);
}
removeTodo(id) {
this.todos.value = this.todos.value.filter(todo => todo.id !== id);
}
// Create a derived atom that sorts todos by creation date
sortedTodos = this.deriveAtom(
[this.todos],
(todos) => {
return [...todos].sort((a, b) => a.createdAt - b.createdAt);
}
);
}
export default TodoStore;
2. Create Todo Components
// TodoInput.jsx
import React, { useState } from 'react';
import { useStore } from 'nucleux';
import TodoStore from './TodoStore';
function TodoInput() {
const [text, setText] = useState('');
const todoStore = useStore(TodoStore);
const handleSubmit = (e) => {
e.preventDefault();
if (text.trim()) {
todoStore.addTodo(text);
setText('');
}
};
return (
<form onSubmit={handleSubmit}>
<input
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="What needs to be done?"
/>
<button type="submit">Add</button>
</form>
);
}
// TodoItem.jsx
import React from 'react';
import { useStore } from 'nucleux';
import TodoStore from './TodoStore';
function TodoItem({ id, text, completed }) {
const todoStore = useStore(TodoStore);
return (
<div style={{ display: 'flex', alignItems: 'center', margin: '8px 0' }}>
<input
type="checkbox"
checked={completed}
onChange={() => todoStore.toggleTodo(id)}
/>
<input
value={text}
onChange={(e) => todoStore.updateTodo(id, e.target.value)}
style={{
margin: '0 8px',
textDecoration: completed ? 'line-through' : 'none'
}}
/>
<button onClick={() => todoStore.removeTodo(id)}>Delete</button>
</div>
);
}
// TodoList.jsx
import React from 'react';
import { useStore, useValue } from 'nucleux';
import TodoStore from './TodoStore';
import TodoItem from './TodoItem';
function TodoList() {
const todoStore = useStore(TodoStore);
const todos = useValue(todoStore.sortedTodos);
return (
<div>
{todos.map(todo => (
<TodoItem key={todo.id} {...todo} />
))}
<div style={{ marginTop: '16px' }}>
{todos.length} item{todos.length !== 1 ? 's' : ''}
</div>
</div>
);
}
// App.jsx
import React from 'react';
import TodoInput from './TodoInput';
import TodoList from './TodoList';
function App() {
return (
<div style={{ maxWidth: '500px', margin: '0 auto', padding: '20px' }}>
<h1>Nucleux Todo App</h1>
<TodoInput />
<TodoList />
</div>
);
}
export default App;
3. Power Features in Action
Let's look at some of the advanced features Nucleux offers:
Built-in Persistence
Notice how we added persistence to our todos with just a string parameter:
todos = this.atom([], 'todos-storage');
This automatically saves todos to localStorage whenever they change and rehydrates them when the app loads.
Derived Atoms
Our sortedTodos
derived atom automatically updates whenever the base todos
atom changes:
sortedTodos = this.deriveAtom(
[this.todos],
(todos) => {
return [...todos].sort((a, b) => a.createdAt - b.createdAt);
}
);
This pattern keeps sorting logic out of your components and ensures consistent behavior throughout your application.
Performance Benefits
Nucleux's atomic update model provides significant performance benefits. Let's visualize what happens when state changes:
With traditional global state:
State changes
Every connected component re-renders
Virtual DOM diffing helps, but unnecessary work still happens
With Nucleux:
State atom changes
Only components subscribed to that specific atom re-render
Other components remain untouched
This approach scales exceptionally well for large applications with complex state dependencies.
Getting Started with Nucleux
Ready to try Nucleux in your project? Installation is straightforward:
# Using npm
npm install nucleux
# Using yarn
yarn add nucleux
# Using pnpm
pnpm add nucleux
Conclusion
State management doesn't have to be complicated. Nucleux proves that you can have both simplicity and power in a single library without compromise.
By combining the best aspects of publisher-subscriber patterns with IoC containers, Nucleux creates a developer experience that feels natural and intuitive. Whether you're building a small React application or a complex enterprise system, Nucleux scales with your needs without introducing unnecessary complexity.
Give Nucleux a try on your next project:
What state management challenges are you facing in your applications? Let me know in the comments, and I'd be happy to discuss how Nucleux might help solve them.
Subscribe to my newsletter
Read articles from Marty Roque directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
