Open5
SolidJS Code Reading
SolidJS のリアクティビティシステムがどのように実装されているか気になるのでコード読む
実装見る前に公式サイトでも紹介されているこの辺りを読んだ方が良さそう。全て SolidJS 作者の Ryan Carniato 氏によって書かれた記事。
Ryan Carniato 氏の記事はこのスクラップで読む
最初に SolidJS の主な特徴
- Not 仮想 DOM
- 高い パフォーマンス
- React と似た構文
- リアクティブな値のみを更新して再レンダリング (コンポーネント関数は 1 回のみ実行される)
リポジトリ構成は pnpm workspace × Turborepo
ビルド周りは Rollup 使っている
本体である packages/solid
から見ていく
まずは package.json から
main
module
browser
exports
の違い
createSignal
本体は packages/solid/src/reactive/signal.ts
にある
export function createSignal<T>(): Signal<T | undefined>;
export function createSignal<T>(value: T, options?: SignalOptions<T>): Signal<T>;
export function createSignal<T>(
value?: T,
options?: SignalOptions<T | undefined>
): Signal<T | undefined> {
options = options ? Object.assign({}, signalOptions, options) : signalOptions;
const s: SignalState<T | undefined> = {
value,
observers: null,
observerSlots: null,
comparator: options.equals || undefined
};
if ("_SOLID_DEV_" && !options.internal) {
if (options.name) s.name = options.name;
registerGraph(s);
}
const setter: Setter<T | undefined> = (value?: unknown) => {
if (typeof value === "function") {
if (Transition && Transition.running && Transition.sources.has(s)) value = value(s.tValue);
else value = value(s.value);
}
return writeSignal(s, value);
};
return [readSignal.bind(s), setter];
}
返り値である Signal
の型。Getter 関数、Setter 関数のタプルを返す。Getter 関数 なことろが React の useState
と異なる。
export type Accessor<T> = () => T;
export type Setter<T> = (undefined extends T ? () => undefined : {}) &
(<U extends T>(value: (prev: T) => U) => U) &
(<U extends T>(value: Exclude<U, Function>) => U) &
(<U extends T>(value: Exclude<U, Function> | ((prev: T) => U)) => U);
export type Signal<T> = [get: Accessor<T>, set: Setter<T>];
SignalOptions 型
export interface BaseOptions {
name?: string;
}
export interface EffectOptions extends BaseOptions {}
export interface MemoOptions<T> extends EffectOptions {
equals?: false | ((prev: T, next: T) => boolean);
}
export interface SignalOptions<T> extends MemoOptions<T> {
internal?: boolean;
}