Skip to content

Instantly share code, notes, and snippets.

@nico-martin
Last active October 16, 2024 13:51
Show Gist options
  • Save nico-martin/9346598c87d45a2b93d6f4547247f243 to your computer and use it in GitHub Desktop.
Save nico-martin/9346598c87d45a2b93d6f4547247f243 to your computer and use it in GitHub Desktop.
Reactive Class values
class MyClass extends EventTarget {
private _value: number = 0;
set value(value: number) {
this._value = value;
this.dispatchEvent(new Event('valueChanged'));
}
get value(): number {
return this._value;
}
public onValueChanged(callback: (value: number) => void) {
const listener = () => callback(this.value);
this.addEventListener('valueChanged', listener);
return () => this.removeEventListener('valueChanged', listener);
}
public countUp() {
this.value++;
}
}
const MyComponent: React.FC = () => {
const [value, setValue] = React.useState<number>(0);
const [instance, setInstance] = React.useState<MyClass>(null);
React.useEffect(() => {
const instance = new MyClass();
const removeListener = instance.onValueChanged((value) => setValue(value));
setInstance(instance);
return () => removeListener();
}, []);
return (
<div>
<p>{value}</p>
<button onClick={() => instance.countUp()}>count up</button>
</div>
);
};
const MyComponentSyncExternalStore: React.FC = () => {
const myInstance = React.useMemo(() => new MyClass(), []);
const value = React.useSyncExternalStore(
(callback) => myInstance.onValueChanged(callback),
() => myInstance.value
);
return (
<div>
<p>{value}</p>
<button onClick={() => myInstance.countUp()}>count up</button>
</div>
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment