Skip to main content
Version: v0.x (deprecated)

Migration Guide: v0.x → v1.0

This version is deprecated

This migration guide is for users of use-less-react v0.x.
If you're already on v1.0, you don't need this guide. For the current documentation, see v1.0.

This guide will help you migrate your codebase from use-less-react v0.x to v1.0. Version 1.0 introduces a new reactivity model based on ReactiveValue and ReactiveObject, replacing the decorator-based approach of v0.x.


Overview of Changes

v0.x (Deprecated)

  • Decorator-based reactivity (@Notifies, @DependsOn)
  • Classes extending PubSub or using PubSubMixin
  • useReactiveInstance hook with dependency arrays
  • makeReactiveProperties for automatic notifications

v1.0 (Current)

  • ReactiveValue and ReactiveObject for fine-grained reactivity
  • useReactiveValues and useReactiveStoreValues hooks
  • Fully declarative reactivity
  • More flexible and composable API

Step 1: Update Dependencies

npm install @dxbox/use-less-react@^1.0.0

Step 2: Migrate Classes

Before (v0.x)

import { PubSub, Notifies } from '@dxbox/use-less-react/classes';

class Counter extends PubSub {
count = 0;

@Notifies('count')
increment() {
this.count++;
}
}

After (v1.0)

import { ReactiveValue, AutoDispose } from '@dxbox/use-less-react/classes';

@AutoDispose
class Counter implements Disposable {
count = new ReactiveValue(0);
// count is automatically detected and disposed

increment() {
this.count.set(c => c + 1);
}

[Symbol.dispose](): void {
// Custom cleanup logic if needed
// @AutoDispose automatically disposes count after this
}
}

Key changes:

  • Use ReactiveValue for individual reactive properties instead of extending PubSub
  • Create reactive properties with new ReactiveValue(initialValue) (see ReactiveValue subclasses, like ReactiveObject, ReactiveArray, etc. )
  • Use .get() and .set() to access and modify values
  • Use @AutoDispose for automatic lifecycle management - it automatically detects all properties that implement Disposable (have Symbol.dispose)

Step 3: Migrate React Hooks

Before (v0.x)

import { useReactiveInstance } from '@dxbox/use-less-react/client';

function CounterComponent({ counter }: { counter: Counter }) {
const { state: count } = useReactiveInstance(
counter,
(instance) => instance.count,
['count']
);

return <div>Count: {count}</div>;
}

After (v1.0)

import { useReactiveValues, useDisposable } from '@dxbox/use-less-react/client';

function CounterComponent() {
const counter = useDisposable(() => new Counter());
const { count } = useReactiveValues({ count: counter.count });

return (
<div>
<div>Count: {count}</div>
<button onClick={() => counter.increment()}>+</button>
</div>
);
}

Key changes:

  • Use useReactiveValues with an object containing ReactiveValue instances
  • Use useDisposable to instantiate classes or plain objects that share the lifecycle of the component (and must be disposed, on unmount)
  • More robust API

Step 4: Migrate Contexts

Before (v0.x)

import { createGenericContext } from '@dxbox/use-less-react/client';

const [CounterProvider, useCounter] = createGenericContext<Counter>();

function App() {
const counterRef = useRef(new Counter());
return (
<CounterProvider value={counterRef.current}>
<CounterComponent />
</CounterProvider>
);
}

After (v1.0)

import { createGenericContext } from '@dxbox/use-less-react/client';

const [CounterProvider, useCounter] = createGenericContext<Counter>();

function App() {
const counter = useDisposable(() => new Counter());
return (
<CounterProvider value={counter}>
<CounterComponent />
</CounterProvider>
);
}

Note: The Generic Context and Hydration Context API is identical.


Step 5: Migrate Prefabs

Command Bus, Query Bus, Event Bus

The bus prefabs have been updated in v1.0. The core concepts remain the same, but the implementation uses the new reactivity model. See the v1.0 Prefabs documentation for details.

Memento Pattern

The Memento pattern in v1.0 works similarly but integrates with ReactiveValue. See the v1.0 Memento documentation for migration details.


Common Patterns

Computed Properties

Before (v0.x):

class Person extends PubSub {
firstName = '';
lastName = '';

@DependsOn('firstName', 'lastName')
get fullName() {
return `${this.firstName} ${this.lastName}`;
}
}

After (v1.0):

import { ReactiveValue, ComputedValue, AutoDispose } from '@dxbox/use-less-react/classes';

@AutoDispose
class Person implements Disposable {
firstName = new ReactiveValue('');
// firstName is automatically detected and disposed (has Symbol.dispose)

lastName = new ReactiveValue('');
// lastName is automatically detected and disposed (has Symbol.dispose)

fullName = new ComputedValue(
() => `${this.firstName.get()} ${this.lastName.get()}`,
[this.firstName, this.lastName]
);
// fullName is automatically detected and disposed (has Symbol.dispose)

[Symbol.dispose](): void {
// Custom cleanup logic if needed
}
}

Multiple Reactive Properties

Before (v0.x):

const { state } = useReactiveInstance(
store,
(s) => ({ count: s.count, name: s.name }),
['count', 'name']
);

After (v1.0):


const counter = new ReactiveValue(0);
const name = new ReactiveValue("John")

const { count, name } = useReactiveValues({
count,
name,
});

See the v1.0 Hooks documentation for migration details.


Need Help?


Next: v1.0 Documentation