Suggestion: Add notify method to allow signal based reactivity

Ouverte
#1,189 0 commentaires 1 réaction 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 4 jours

Personne n'a encore pris cette issue.

Évaluation

Difficulté
4/5
Temps estimé
3-5 jours
Accessibilité débutants
45/100
Type d'issue
Fonctionnalité
Clarté
Plutôt claire
Activité
À l'abandon
Stack technique
typescript
Domaine
frontend

Piste de recherche

Commencez dans createProxyProxy et examinez l’initialisation de ProxyState, puis suivez objectTraps.set et originalObjectTrapsSet. Comparez le hook de notification optionnel proposé avec le flux de createDraft et finishDraft ainsi qu’avec l’exemple Svelte ; c’est terminé lorsque les consommateurs basés sur des signaux peuvent recevoir les modifications du draft sans affecter le comportement existant lorsque le hook n’est pas défini.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

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];
}
Langage dominant
JavaScript
Étoiles
29k
Forks
905
Merge moyen
3 j 16 h
PR mergées (30 j)
22

Préparer son environnement

Ce projet ne fournit ni conteneur de développement, ni Dockerfile, ni guide de contribution : l'installation est à votre charge. Commencez par son README, et consultez notre guide de la première contribution pour les étapes générales.

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de immerjs/immer

Toutes les issues de immerjs/immer

Issues similaires

Plus d'issues JavaScript

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.