Propagation Boundary: blocking updates/fetches/effects within a scope
维护者通常 1 天内回复
还没有人认领这个 Issue。
评估
- 难度
- 5/5
- 预计耗时
- 一周以上
- 新手友好度
- 35/100
- Issue 类型
- 功能
- 描述清晰度
- 基本清楚
- 活跃度
- 冷清
- 技术栈
- typescript
- 领域
- frontend, performance
调研方向
先阅读提议的 PropagationBoundary 或 Freeze 行为以及 Owner 方案,然后跟踪在 Solid 1.0 中读取、写入、effects 和异步工作如何跨越作用域。完成的标准是达成一致的 API,并定义向下和向上的传播规则,包括是否需要 escape hatch;issue 中没有指定文件或测试。
由索引模型根据 Issue 内容生成。
描述
This is an enhancement issue following this Discord conversation between Ryan and myself.
Usecase
I'm trying to write a router that is as fast for SPAs as the native browser history is for old-fashioned MPAs, especially when a user goes back in their history. For this I want to keep previous pages in memory, including their DOM nodes. However, while they are in an invisible/cached state, I don't want them to trigger fetches etc.
For example, imagine a shopping site. The current "shopping cart" is essentially global state. I visit a page /details that shows me price details of my shopping cart. Part of its implementation behaves somewhat like this:
<For each={shoppingCart()}>
{(item) => <Item price={fetchCurrentPriceForItem(item().id)} name={item().name}/>}
</For>
I then want to add something else to my shopping cart so I navigate to /search?q=something+else. I add it to my shopping cart. Now the shoppingCart() signal updates in the cached /details page, and fetches pricing details I didn't need fetching for. There may also be effects running that are wasting CPU.
My example is very simplified but I had variations of this problem in "real" code (using Solid 1.0) too. I ended up defining a isPageVisible() signal that so any refetch only happens when it is true, but then you have to wire that signal through all your effects. This also only solves the issue for effects/resources, but Solid still "wastes" CPU cycles updating other parts of the DOM.
Proposed solution
A minimal API:
<PropagationBoundary block={isPageVisible()}>
...
</PropagationBoundary>
When block == true, all elements nested within the PropagationBoundary will no longer update, run any effects or do any async stuff. Alternatively we can name it Freeze to signal that its contents will be frozen regardless of state changes.
In the Discord thread we also talked about more exotic extra options, for example only running effects on animationFrame. I'm currently not sure how that would fit within this concept of a propagation boundary.
I'd also be fine with this being an optional argument block: () => boolean when creating an Owner. It may simplify the implementation, and I'm creating an Owner for each page anyway.
Considerations
Updates flowing "upwards"
Coming back to the example, shoppingCart is "top-level" state and its updates travel "down" to the page and eventually its <Item/> components. If at any point an active propagation boundary is encountered, updates shouldn't propagate. Conceptually quite simple.
However, an update may also trigger "within" a propagation boundary and travel "upward". For example: the /details page somehow triggers an update to a signal that is displayed in the header of the page. This should naturally occur less frequently, but we should clearly define what happens anyway: do we block it or not? Personally I think there are arguments for both cases.
Intuitively I'd expect it is easiest to ignore the source of the update/write. The rule would be simple then: if a read happens inside an active propagation boundary, it will never see new state. This intuition is however based on Solid 1.0, so take it with a grain of salt.
Escape hatch
I proposed a withoutBoundary helper to Ryan that would unblock propagation while in an active propagation boundary. I currently don't see a need for it anymore, unless the behaviour for "upwards" updates becomes more complex than what I suggested above.
Alternative name: "Freeze"
Maybe PropagationBoundary is rather technical, and it's better to describe the resulting behaviour rather than the way it is implemented. In that case I'd suggest Freeze, as it "freezes" the contents and any associated effects. Happy to hear your thoughts.
- 主要语言
- TypeScript
- 星标
- 36.2k
- 派生
- 1.1k
- 平均合并
- 9 小时 56 分钟
- 30 天内合并 PR
- 487
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
solidjs/solid 的其他 Issue
-
难度 4/5 3-5 天 新手友好度 55/100
维护者通常 1 天内回复
-
难度 4/5 3-5 天 新手友好度 45/100
维护者通常 1 天内回复
-
难度 4/5 3-5 天 新手友好度 35/100
维护者通常 1 天内回复
-
难度 5/5 一周以上 新手友好度 22/100
维护者通常 1 天内回复
-
What gets passed to the `when` prop of a `Show` still gets executed twice on SSR可能已有人在做 @brenelz 于 5 天前认领。 未关闭1.x
难度 3/5 1-2 天 新手友好度 52/100
维护者通常 1 天内回复
相似的 Issue
-
unwrapDatabaseError masks real DB errors with TypeError: Cannot convert object to primitive value未关闭
难度 2/5 1-3 小时 新手友好度 74/100
NEARBuilders/everything-dev#798 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 78/100
vercel-labs/durable-harness#53 ·
维护者通常 1 天内回复
-
[Bug]: Redesign tab bars ignore clicks on Linux: hidden chat layers keep window drag regions可能已有人在做 关联的 PR 仍在进行中或已合并。 未关闭
难度 2/5 1-3 小时 新手友好度 82/100
维护者通常 1 天内回复
-
experiência: a doc manda subir para o Micro do Supabase, mas não diz que exige plano pago nem quanto custa可能已有人在做 关联的 PR 仍在进行中或已合并。 未关闭area/docs area/ui enhancement
难度 1/5 1-3 小时 新手友好度 88/100
melgarafael/DeskcommCRM#4098 ·
维护者通常 1 天内回复
-
dependencies platform: ios
难度 1/5 1-3 小时 新手友好度 78/100
software-mansion/react-native-executorch#1617 ·
维护者通常 1 天内回复