Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save HamedFathi/7679c54a1f818b035c03813fe49b89af to your computer and use it in GitHub Desktop.
Save HamedFathi/7679c54a1f818b035c03813fe49b89af to your computer and use it in GitHub Desktop.
// https://dev.to/ryansolid/building-a-reactive-library-from-scratch-1i0p
// https://www.youtube.com/watch?v=vHy7GRpTpm8&list=LL&index=3&t=514s
// https://codesandbox.io/s/0xyqf?file=/reactive.js:0-1088
// A Dependency has many different Subscribers depending on it
// A particular Subscriber has many Dependencies
type Dependency = Set<Subscriber>;
type Subscriber = {
execute(): void;
dependencies: Set<Dependency>;
};
type Signal<T> = [() => T, (value: T) => void];
const context: Subscriber[] = [];
function createSignal<T>(value: T): Signal<T> {
const subscriptions: Dependency = new Set<Subscriber>();
const read = (): T => {
const running = context[context.length - 1];
if (running) {
subscriptions.add(running);
running.dependencies.add(subscriptions);
}
return value;
};
const write = (nextValue: T) => {
value = nextValue;
for (const sub of [...subscriptions]) {
sub.execute();
}
};
return [read, write];
}
function cleanup(running: Subscriber) {
for (const dep of running.dependencies) {
dep.delete(running);
}
running.dependencies.clear();
}
function createEffect(effect: () => void) {
const execute = () => {
cleanup(running);
context.push(running);
try {
effect();
} finally {
context.pop();
}
};
const running: Subscriber = {
execute,
dependencies: new Set(),
};
execute();
}
function createMemo<T>(fn: () => T): () => T {
const [read, write] = createSignal<T>(null as any);
createEffect(() => write(fn()));
return read;
}
// util
function log(...args: unknown[]) {
console.log(args.join(' '));
}
// index
log('1. Create');
const [firstName, _setFirstName] = createSignal('John');
const [lastName, setLastName] = createSignal('Smith');
const [showFullName, setShowFullName] = createSignal(true);
const displayName = createMemo(() =>
showFullName() ? `${firstName()} ${lastName()}` : firstName()
);
console.clear();
createEffect(() => log('My name is', displayName()));
log('2. Set showFullName: false ');
setShowFullName(false);
log('3. Change lastName');
setLastName('Legend');
log('4. Set showFullName: true');
setShowFullName(true);
log('5. Change lastName while showFullName: true');
setLastName('Who');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment