Suggestion: Add notify method to allow signal based reactivity

Offen
#1,189 0 Kommentare 1 Reaktion 0 zugewiesene Personen Auf GitHub ansehen

Maintainer antworten meist innerhalb von 4 Tagen

Dieses Issue hat noch niemand übernommen.

Bewertung

Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Anfängerfreundlichkeit
45/100
Issue-Typ
Feature
Klarheit
Größtenteils klar
Aktivitätsstatus
Veraltet
Tech-Stack
typescript
Bereich
frontend

Rechercherichtung

Beginne in createProxyProxy und untersuche die Initialisierung von ProxyState; verfolge dann objectTraps.set und originalObjectTrapsSet. Vergleiche den vorgeschlagenen optionalen Benachrichtigungs-Hook mit dem Ablauf von createDraft und finishDraft sowie dem Svelte-Beispiel; abgeschlossen ist die Aufgabe, wenn signalbasierte Consumer Entwurfsänderungen empfangen können, ohne dass sich das bestehende Verhalten ändert, wenn der Hook nicht gesetzt ist.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

proposal

🚀 Feature Proposal

Add an optional notfy_ function to the ProxyState that defaults to null. So that the state in createProxyProxy looks like this:


const state: ProxyState = {
	type_: isArray ? ArchType.Array : (ArchType.Object as any),
	// Track which produce call this is associated with.
	scope_: parent ? parent.scope_ : getCurrentScope()!,
	// True for both shallow and deep changes.
	modified_: false,
	// Used during finalization.
	finalized_: false,
	// Track which properties have been assigned (true) or deleted (false).
	assigned_: {},
	// The parent draft state.
	parent_: parent,
	// The base state.
	base_: base,
	// The base proxy.
	draft_: null as any, // set below
	// The base copy with any updated values.
	copy_: null,
	// Called by the `produce` function.
	revoke_: null as any,
	isManual_: false,

	// new optional method for change notification; defaulting to null
	notify_: null
}

and then updating the object trap to wrap the set function:

 export const objectTraps: ProxyHandler<ProxyState> = {
	...
	set(state: ProxyObjectState, prop: string /* strictly not, but helps TS */, value) {
		const res = originalObjectTrapsSet(state,prop,value)
	
		if(state.notify_) state.notify_()
		return res 
	}

Motivation

The immer Proxy does not play nice with the svelte 5 rune proxy. Adding the notify_ method would allow adding reactivity to drafts.
I can't see any downsides in having the notify_ method as it has no noticeable performance impact when not used, is backwards compatible and opt in.

Can this be solved in user-land code?

I have not found a satisfying user land solution. Doesn't mean there isn't one

Example

A simple implementation that allows the default svelte 5 bind:value on inputs. Comments on svelte specific code; would work similar with other signal based systems.

const DRAFT_IMMER_PROXY = Symbol.for('og-immer-proxy');

function makeDraft<T extends object>(data: T) {
	const draft = createDraft(data);

	//update is a svelte internal signal to notify dependent values 
	const subscribe = createSubscriber((update) => {
		draft[DRAFT_STATE].notify_ = () => {
			update();
		};
	});

	const traps: ProxyHandler<Draft<T>> = {
		get(target, p, receiver) {
			if (p == DRAFT_IMMER_PROXY) {
				return draft;
			}
			
			// create svelte subscription
			subscribe();
			return Reflect.get(target, p, receiver);
		}
	};
	const proxy = new Proxy(draft, traps);

	return proxy;
}

function commit(draft: Draft<any>) {
	const immerDrat = draft[DRAFT_IMMER_PROXY];
	if (!immerDrat) return;
	let fwd;
	let bwd;
	const res = finishDraft(immerDrat, (p, u) => {
		fwd = p;
		bwd = u;
	});
	return [res, fwd, bwd];
}
Vorherrschende Sprache
JavaScript
Sterne
29k
Forks
905
Ø Merge
3 T. 16 Std.
Gemergte PRs (30 T.)
22

Entwicklungsumgebung

Dieses Projekt bietet weder Dev-Container noch Dockerfile noch Beitragsleitfaden – die Einrichtung liegt bei Ihnen. Beginnen Sie mit der README; die allgemeinen Schritte stehen in unserem Leitfaden für den ersten Beitrag.

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus immerjs/immer

Alle Issues in immerjs/immer

Ähnliche Issues

Weitere Issues zu JavaScript

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.