Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

createPresence effect reads and writes mountedItem (Solid 2 EFFECT_WRITES_OWN_SOURCE)

Đang mở Phù hợp với người mới
#1,082 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

Chưa có ai nhận issue này.

Đánh giá

Độ khó
2/5
Thời gian dự kiến
1-3 giờ
Mức phù hợp với người mới
85/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
typescript
Lĩnh vực
frontend

Hướng nghiên cứu

Bắt đầu tại packages/presence/src/index.ts, quanh effect createPresence ở dòng 161–174, và đọc cách item() cùng isMounted() điều khiển các lần cập nhật. Issue đề xuất cách sửa bằng createEffect(compute, apply) và untrack(mountedItem). Tái hiện bằng cách mở nút trong ví dụ được cung cấp. Hoàn tất khi thao tác đó không còn báo EFFECT_WRITES_OWN_SOURCE và hành vi thoát rồi mới chuyển đổi vẫn được giữ nguyên.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

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)
Ngôn ngữ chính
TypeScript
Star
1.6k
Fork
165
Merge trung bình
1 ngày 13 giờ
Pull request đã merge (30 ngày)
15

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của solidjs-community/solid-primitives

Tất cả issue của solidjs-community/solid-primitives

Issue tương tự

Thêm issue về TypeScript

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.