This project is an experiment to bring Svelte 5's reactivity and ergonomics to a Next.js (React) codebase. It uses a custom runes system for state, derived values, and effects, and introduces a Svelte-inspired $
hook for simple, reactive subscriptions in React components.
$
(dollar sign)To get started, clone the repository and install dependencies:
npm install react-runes
$
reactivity.$
).state(initial)
: Create a reactive state value. You must use .value
to access/mutate.$state(initial)
: Creates a reactive proxy. No .value
needed for objects.derived(fn)
: Create a computed value that updates when dependencies change. Must use .value
.$derived(fn)
: Creates a reactive proxy for computed values. No .value
needed.effect(fn)
: Run side effects when dependencies change.untrack(fn)
: Execute a function without tracking its dependencies.$
Hookconst value = $(rune)
$
syntax for reactive values.Here's an example that shows how to use $state
and $derived
with a user object.
import { $state, $derived, effect, $ } from 'react-runes';
// Create a reactive user object
const user = $state({
firstName: 'John',
lastName: 'Doe',
});
// Create a derived value for the full name
const fullName = $derived(() => `${user.firstName} ${user.lastName}`);
effect(() => {
console.log('User changed:', user.firstName, user.lastName);
});
export default function UserProfile() {
const localUser = $(user);
const localFullName = $(fullName);
return (
<div>
<p>First Name: {localUser.firstName}</p>
<p>Last Name: {localUser.lastName}</p>
<p>Full Name: {localFullName}</p>
<input
type="text"
value={localUser.firstName}
onChange={(e) => (user.firstName = e.target.value)}
className="border p-2 rounded"
/>
<input
type="text"
value={localUser.lastName}
onChange={(e) => (user.lastName = e.target.value)}
className="border p-2 rounded"
/>
</div>
);
}
Each feature/component lives in its own directory, colocated with its store and logic:
components/
user-profile/
user-profile.tsx
user.ts // user rune is defined here
import { user, fullName } from './user';
$
?$
as a hook.This is a playground for reactivity experiments. PRs and ideas welcome!
MIT