Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

createPresence effect reads and writes mountedItem (Solid 2 EFFECT_WRITES_OWN_SOURCE)

未关闭 适合新手
#1,082 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

还没有人认领这个 Issue。

评估

难度
2/5
预计耗时
1-3 小时
新手友好度
85/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
技术栈
typescript
领域
frontend

调研方向

从 packages/presence/src/index.ts 第 161–174 行附近的 createPresence effect 开始,阅读 item() 和 isMounted() 如何驱动其更新。Issue 提供了使用 createEffect(compute, apply) 和 untrack(mountedItem) 的建议修复方案。在提供的示例中打开按钮以复现。完成的标准是该交互不再报告 EFFECT_WRITES_OWN_SOURCE,并且先退出再切换的行为保持不变。

由索引模型根据 Issue 内容生成。

描述

Describe the bug

createPresence keeps the mounted item in sync with an effect that both reads mountedItem() and writes it with setMountedItem. On Solid 2 that is EFFECT_WRITES_OWN_SOURCE: the effect re-runs because of its own write, settles in two flushes, and the first frame renders the pre-write value.

mountedItem only needs to be sampled when item() or isMounted() changes. It should not be a tracked input of the effect that writes it.

This shows up when opening a Kobalte Popover (@kobalte/[email protected]). Popover calls createPresence(() => forceMount || isOpen() || undefined, { transitionDuration: 0 }). The dev console reports:

[EFFECT_WRITES_OWN_SOURCE] effect "effect" re-ran because of its own write: it wrote "signal", which fed back into its inputs. Two flushes to settle, and the screen rendered the pre-write value in between. The written value is a function of what the effect reads — compute it in a memo (or normalize where the source is written) instead of correcting it after the fact.
  in <Popover> › effect

The same effect is in packages/presence/src/index.ts on main (1.0.0-next.4) and in the published 1.0.0-next.2 build. The published build already splits this into Solid 2's createEffect(compute, apply), but the compute still tracks mountedItem().

createEffect(() => {
  if (mountedItem() !== item()) {
    if (isMounted()) {
      setShouldBeMounted(false);
    } else if (itemShouldBeMounted(item())) {
      setMountedItem(() => item());
      setShouldBeMounted(true);
    }
  } else if (!itemShouldBeMounted(item())) {
    setShouldBeMounted(false);
  } else if (itemShouldBeMounted(item())) {
    setShouldBeMounted(true);
  }
});

Suggested repair

Track item() and isMounted() only. Read the previous item with untrack(mountedItem) in the apply. Exit-then-swap stays: a change while still mounted only calls setShouldBeMounted(false); the swap still runs on the later pass, because that pass is driven by isMounted() becoming false, not by the mountedItem write.

createEffect(
  () => [item(), isMounted()] as const,
  ([currentItem, isM]) => {
    const mounted = untrack(mountedItem);
    if (mounted !== currentItem) {
      if (isM) setShouldBeMounted(false);
      else if (itemShouldBeMounted(currentItem)) {
        setMountedItem(() => currentItem);
        setShouldBeMounted(true);
      }
    } else if (!itemShouldBeMounted(currentItem)) setShouldBeMounted(false);
    else if (itemShouldBeMounted(currentItem)) setShouldBeMounted(true);
  },
);

Reproduction

import { createSignal } from "solid-js";
import { createPresence } from "@solid-primitives/presence";

export default function App() {
  const [open, setOpen] = createSignal(false);
  createPresence(open, { transitionDuration: 0 });
  return <button onClick={() => setOpen(true)}>Open</button>;
}

Click Open. The dev console reports EFFECT_WRITES_OWN_SOURCE as above.

Versions

  • @solid-primitives/presence 1.0.0-next.2 (same effect on main / 1.0.0-next.4)
  • solid-js 2.0.0-rc.15
  • @kobalte/core 2.0.0-alpha.4 (how we hit it; the bug is in presence)
主要语言
TypeScript
星标
1.6k
派生
165
平均合并
12 小时 35 分钟
30 天内合并 PR
14

环境准备

  • 没有 Dockerfile 或 Docker Compose 文件
  • 没有 Pull Request 模板
  • 阅读贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

solidjs-community/solid-primitives 的其他 Issue

查看 solidjs-community/solid-primitives 的全部 Issue

相似的 Issue

更多 TypeScript Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。