theater-mutable-react
v0.0.1
Published
A React library for building mutable data structures based on the theater-mutable library
Readme
theater-mutable-react
A React library for integrating with theater-mutable - providing components and hooks for reactive state management.
This library offers React bindings for theater-mutable, allowing you to:
- Use mutable values in React components
- Iterate over mutable lists with the
<Each>component - Read and display mutable values with the
<Read>component - Create and manage mutable state with hooks like
useMutableanduseRead - Work with global mutable state across your application
The components and hooks provide a seamless integration between theater-mutable's reactive state management and React's component lifecycle and rendering system.
Installation
bun install theater-mutable-reactHow to use it
Here's a complete example of a TodoList application using all the components and hooks:
import { useRead, useMutable, Each, Read, Show } from "theater-mutable-react";
import { write, read } from "theater-mutable";
function TodoList() {
// Create mutable state for todos and new todo input
const todos = useMutable([]);
const newTodo = useMutable("");
// Create a derived state using useSelector
const completedCount = useSelector(
[todos],
(todos) => todos.filter((todo) => todo.completed).length
);
const addTodo = () => {
if (newTodo.value) {
write(todos, [
...todos.value,
{
id: Date.now(),
text: newTodo.value,
completed: false,
},
]);
write(newTodo, "");
}
};
const toggleTodo = (id) => {
write(
todos,
todos.value.map((todo) =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
)
);
};
return (
<div>
<h1>Todo List</h1>
{/* Show completed count using Read component */}
<Read mutable={completedCount}>
{(count) => <p>Completed: {count}</p>}
</Read>
{/* Input for new todo */}
<input
value={useRead(newTodo)}
onChange={(e) => write(newTodo, e.target.value)}
onKeyPress={(e) => e.key === "Enter" && addTodo()}
/>
<button onClick={addTodo}>Add Todo</button>
{/* List todos using Each component */}
<Each list={todos}>
{(todo) => (
<div>
<Read mutable={todo.completed}>
{(completed) => (
<input
type="checkbox"
checked={completed}
onChange={() => toggleTodo(useRead(todo.id))}
/>
)}
</Read>
<Read mutable={todo.text}>{(text) => <span>{text}</span>}</Read>
</div>
)}
</Each>
{/* Show empty state using Show component */}
<Show mutable={todos} fallback={<p>No todos yet!</p>}>
{(todos) => todos.length === 0 && <p>No todos yet!</p>}
</Show>
</div>
);
}API Reference
Components
<Each>
A component for iterating over mutable lists. It automatically handles key props and listens to list changes. The children function receives a Mutable value that you can read using the <Read> component.
const list = useMutable([1, 2, 3]);
<Each list={list}>
{(value) => <Read mutable={value}>{(value) => <div>{value}</div>}</Read>}
</Each>;<Read>
A component that reads and displays a mutable value. It automatically updates when the value changes.
const count = useMutable(0)
<Read mutable={count}>
{value => <div>{value}</div>}
</Read><Show>
A component that conditionally renders content based on a mutable value. It accepts a fallback prop for when the value is empty.
const value = useMutable('Hello')
<Show mutable={value} fallback={<div>No value</div>}>
{content => <div>{content}</div>}
</Show>Hooks
useMutable
Creates a mutable value that can be used in React components.
const count = useMutable(0);
write(count, 1); // Update the valueuseRead
Returns the current value of a mutable and updates when it changes.
const count = useMutable(0);
const value = useRead(count); // Returns 0useSelector
Creates a derived value from one or more mutable values. It updates whenever any of the source values change.
const count = useMutable(1);
const doubled = useSelector([count], (value) => value * 2); // Returns 2Utilities
createGlobalMutable
Creates a global mutable value using React's context API. Returns a provider component and a hook to access the value.
const [CounterProvider, useCounter] = createGlobalMutable(0);
function App() {
return (
<CounterProvider>
<Counter />
</CounterProvider>
);
}
function Counter() {
const counter = useCounter();
return <div>{useRead(counter)}</div>;
}