| 1 | import { useLayoutEffect, useRef } from "react"; |
| 2 | |
| 3 | export type CommittedSlot<Value> = { |
| 4 | value?: Value; |
| 5 | epoch: number; |
| 6 | phase: "not-ready" | "ready" | "disposed"; |
| 7 | requestId: number; |
| 8 | }; |
| 9 | |
| 10 | /** Commit is the only publication boundary; cleanup synchronously revokes it. */ |
| 11 | export function useCommittedSlot<Value>(value: Value): CommittedSlot<Value> { |
| 12 | const slotRef = useRef<CommittedSlot<Value>>({ epoch: 0, phase: "not-ready", requestId: 0 }); |
| 13 | const slot = slotRef.current; |
| 14 | useLayoutEffect(() => { |
| 15 | if (slot.phase !== "ready") slot.epoch += 1; |
| 16 | slot.phase = "ready"; |
| 17 | slot.value = value; |
| 18 | }); |
| 19 | useLayoutEffect(() => () => { |
| 20 | slot.phase = "disposed"; |
| 21 | slot.value = undefined; |
| 22 | }, [slot]); |
| 23 | return slot; |
| 24 | } |
| 25 |