Computed
Computed Chunks in Stunk allow you to create state derived from other chunks in a reactive way. Unlike derived chunks, computed chunks can depend on multiple sources, and they automatically recalculate when any of the source chunks change.
import { chunk, computed } from "stunk";
// Define base chunks
const firstNameChunk = chunk("Olamide");
const lastNameChunk = chunk("David");
const ageChunk = chunk(25);
Create a computed
chunk, then subscribe to receive updates
const fullInfoChunk = computed(
// takes the multiple chunk as dependecy array.
[firstNameChunk, lastNameChunk, ageChunk],
(firstName, lastName, age) => ({
fullName: `${firstName} ${lastName}`,
isAdult: age >= 18,
})
);
// Subscribe to changes
fullInfoChunk.subscribe((info) => console.log("Updated Info:", info));
Update dependencies
// Update dependencies
firstNameChunk.set("John"); // ✅ fullInfoChunk updates automatically
ageChunk.set(16); // ✅ isAdult will update to false
computed
example: cartTotalChunk
, which calculates the total price based on cart items.
import { chunk, computed } from "stunk";
// Define base chunks
const cartItemsChunk = chunk([
{ name: "Laptop", price: 1000, quantity: 1 },
{ name: "Mouse", price: 50, quantity: 2 },
]);
Create a computed
chunk, then subscribe to receive updates
// Create a computed chunk
const cartTotalChunk = computed([cartItemsChunk], (cartItems) => ({
totalItems: cartItems.reduce((sum, item) => sum + item.quantity, 0),
totalPrice: cartItems.reduce(
(sum, item) => sum + item.price * item.quantity,
0
),
}));
// Subscribe to changes
cartTotalChunk.subscribe((cartTotal) =>
console.log("Updated Cart:", cartTotal)
);
Update dependencies
// Update dependencies
cartItemsChunk.set([
...cartItemsChunk.get(),
{ name: "Keyboard", price: 80, quantity: 1 },
]);
// ✅ `totalItems` and `totalPrice` update automatically
Advanced Examples
computed
example: userStatusChunk
, which tracks the online status of users and calculates active/inactive counts dynamically.
import { chunk, computed } from "stunk";
// Define base chunks
const usersChunk = chunk([
{ id: 1, name: "Alice", online: true },
{ id: 2, name: "Bob", online: false },
{ id: 3, name: "Charlie", online: true },
]);
const showOnlineOnlyChunk = chunk(false); // Toggle to show only online users
Create a computed
chunk, then subscribe to receive updates
// Create a computed chunk
const userStatusChunk = computed(
[usersChunk, showOnlineOnlyChunk],
(users, showOnlineOnly) => {
// Filter users if showOnlineOnly is true
const filteredUsers = showOnlineOnly
? users.filter((user) => user.online)
: users;
return {
totalUsers: users.length,
onlineUsers: users.filter((user) => user.online).length,
offlineUsers: users.filter((user) => !user.online).length,
displayedUsers: filteredUsers,
};
}
);
// Subscribe to changes
userStatusChunk.subscribe((status) =>
console.log("Updated User Status:", status)
);
Update dependencies
// Update dependencies
showOnlineOnlyChunk.set(true); // ✅ Only online users will be displayed
usersChunk.set([...usersChunk.get(), { id: 4, name: "David", online: true }]); // ✅ Updates dynamically when users change
usersChunk.set([
{ id: 1, name: "Alice", online: false },
{ id: 2, name: "Bob", online: true },
{ id: 3, name: "Charlie", online: false },
{ id: 4, name: "David", online: true },
]);
// ✅ Updates user counts reactively
computed
example: filteredAndSortedTodosChunk
, which dynamically filters and sorts todos based on user-selected criteria.
import { chunk, computed } from "stunk";
// Define base chunks
const todosChunk = chunk([
{ id: 1, text: "Learn Stunk", completed: true, priority: "high" },
{ id: 2, text: "Build a project", completed: false, priority: "medium" },
{ id: 3, text: "Read a book", completed: false, priority: "low" },
]);
const filterChunk = chunk<"all" | "completed" | "active">("all");
const sortChunk = chunk<"priority" | "alphabetical">("priority");
// Create a computed chunk
const filteredAndSortedTodosChunk = computed(
[todosChunk, filterChunk, sortChunk],
(todos, filter, sort) => {
// Apply filtering
let filteredTodos = todos;
if (filter === "completed") {
filteredTodos = todos.filter((todo) => todo.completed);
} else if (filter === "active") {
filteredTodos = todos.filter((todo) => !todo.completed);
}
// Apply sorting
if (sort === "priority") {
filteredTodos = filteredTodos.sort((a, b) => {
const priorityOrder = { high: 1, medium: 2, low: 3 };
return priorityOrder[a.priority] - priorityOrder[b.priority];
});
} else if (sort === "alphabetical") {
filteredTodos = filteredTodos.sort((a, b) =>
a.text.localeCompare(b.text)
);
}
return filteredTodos;
}
);
// Subscribe to changes
filteredAndSortedTodosChunk.subscribe((todos) =>
console.log("Updated Todos:", todos)
);
Update dependencies
// Update dependencies
filterChunk.set("active"); // ✅ Filters only active todos
sortChunk.set("alphabetical"); // ✅ Sorts alphabetically
todosChunk.set([
...todosChunk.get(),
{ id: 4, text: "Workout", completed: false, priority: "high" },
]);
// ✅ Updates reactively based on filter & sort
Why Use Computed Chunks?
✅ Automatic Updates → Recomputes when dependencies change.
✅ Optimized Performance → Only recomputes when needed.
✅ Derived State → Keeps logic clean and centralized.
computed
chunks are ideal for scenarios where state depends on multiple sources or needs complex calculations. They ensure your application remains performant and maintainable.