2.0.0-rc.20: createTrackedEffect never re-runs when a dependency is written earlier in the same effect pass

Aperta
#4,598 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
28/100
Tipo di issue
Bug
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
javascript, typescript
Ambito
frontend

Direzione di ricerca

The bug is in the reactive core: start with dist/dev.js and the tracked effect's first-run path, where the staged write is propagated before the effect links its dependency, and the staleReader / _reruns logic that does not cover EFFECT_TRACKED nodes. Run the two repro snippets in the issue to confirm the logged values are [0] instead of [0, 1]. Done when both cases log [0, 1] and the existing tracked-effect tests still pass.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Describe the bug

A createTrackedEffect whose dependency is written in the same effect pass, before the tracked effect's first run, reads the committed (old) value and never re-runs once the write commits.

Two common shapes:

  1. another effect writes the dependency on its first run;
  2. a parent's onSettled writes a signal passed to the child as a prop.

createEffect(compute, fn) sees the write in both cases (its effect runs again with the new value), so the difference is specific to the tracked effect. A write made by the component's own onSettled, or after the first flush, is seen.

Your Example Website or App

Self-contained repro below (no external link).

Steps to Reproduce the Bug or Issue
import { createEffect, createSignal, createTrackedEffect, flush, onSettled } from 'solid-js'
import { render } from '@solidjs/web'

// 1. Written by another effect on its first run
const log: number[] = []
function C() {
  const [s, setS] = createSignal(0)
  createEffect(() => 1, () => { setS(1) })
  createTrackedEffect(() => { log.push(s()) })
  return null
}
render(() => <C />, document.body)
flush(); await Promise.resolve(); flush()
console.log(log) // [0]  — expected [0, 1]

// 2. Prop written by the parent's onSettled
const log2: number[] = []
function Child(props: { v: number }) {
  createTrackedEffect(() => { log2.push(props.v) })
  return null
}
function Parent() {
  const [s, setS] = createSignal(0)
  onSettled(() => { setS(1) })
  return <Child v={s()} />
}
render(() => <Parent />, document.body)
flush(); await Promise.resolve(); flush()
console.log(log2) // [0]  — expected [0, 1]

Replacing createTrackedEffect(() => log.push(s())) with createEffect(() => s(), (v) => log.push(v)) logs [0, 1] (resp. ends on 1) in both cases.

Expected behavior

The tracked effect re-runs with 1 after the write commits, as createEffect(compute, fn) does.

Screenshots or Videos

No response

Platform
  • solid-js / @solidjs/signals / @solidjs/web: 2.0.0-rc.20 (client build)
  • Reproduced in Chromium (Vitest Browser Mode) and jsdom
  • OS: Linux
Additional context

Reading dist/dev.js: the tracked effect's first run is enqueued on the heap and runs in the user effect queue; the staged write seems to have been propagated to subscribers before the tracked effect linked its dependency, so the commit at the end of the flush notifies nobody. The stale-reader re-derivation (staleReader / _reruns) does not appear to cover EFFECT_TRACKED nodes.

Impact: in an app migrated from 1.x, this silently froze several views on their initial value (a page stuck on "loading", a PDF page indicator, tab state restored from the URL). We worked around it by converting tracked effects to createEffect(compute, fn).

Lingua principale
TypeScript
Stelle
36.2k
Fork
1.1k
Merge medio
11h 5m
PR unite (30g)
475

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di solidjs/solid

Tutte le issue di solidjs/solid

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.