Migration Guide: v0.x → v1.0
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
PubSubor usingPubSubMixin useReactiveInstancehook with dependency arraysmakeReactivePropertiesfor automatic notifications
v1.0 (Current)
ReactiveValueandReactiveObjectfor fine-grained reactivityuseReactiveValuesanduseReactiveStoreValueshooks- 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
ReactiveValuefor individual reactive properties instead of extendingPubSub - Create reactive properties with
new ReactiveValue(initialValue)(seeReactiveValuesubclasses, likeReactiveObject,ReactiveArray, etc. ) - Use
.get()and.set()to access and modify values - Use
@AutoDisposefor automatic lifecycle management - it automatically detects all properties that implementDisposable(haveSymbol.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
useReactiveValueswith an object containingReactiveValueinstances - Use
useDisposableto 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?
- See the v1.0 Documentation for complete API reference
- Check the v1.0 Getting Started guide
- Open an issue on GitHub
Next: v1.0 Documentation