mcpField
S
solidjs-patterns

solidjs-patterns

github.com/different-ai开发24.3k570 次安装今天更新
代码仓库

关于 solidjs-patterns

记录 OpenWork 所用 SolidJS 界面模式的开发技能,面向维护其界面的开发者。内容侧重细粒度信号和按操作隔离异步状态,以减少状态耦合问题。

主要功能

  1. 01优先使用细粒度信号
  2. 02为各操作单独管理待处理状态
  3. 03用 createMemo() 派生界面状态
  4. 04以不可变方式更新信号数据
  5. 05在 await 前保存信号值快照

适用场景

  1. 01避免无关操作彼此禁用
  2. 02管理并行异步操作
  3. 03避免异步处理器读取过期值

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/different-ai/openwork --skill solidjs-patterns

安装后在 Claude Code 中输入/solidjs-patterns确认已加载。

详细介绍

此技能的由来

OpenWork 的 UI 使用 SolidJS:它通过 信号 更新,而不是像 React 那样重新渲染。 大多数“UI 卡住”问题其实是 状态耦合 问题(例如,一个全局 busy() 禁用了无关操作),而不是重新渲染问题。

此技能总结了我们希望在 OpenWork 中始终采用的模式。

核心规则

  • 优先使用 细粒度信号,而不是共享的全局标志。
  • 将异步操作 限定在各自范围内(每个操作都有自己的 pending 状态)。
  • 使用 createMemo() 派生 UI 状态,而不是重复定义布尔值。
  • 避免修改存储在信号中的数组或对象;始终创建新值。

限定范围的异步操作(推荐)

如果某项操作可能与其他操作重叠(权限、安装、后台刷新),不要重复使用全局 busy()。

为每个操作使用专用信号:

const [replying, setReplying] = createSignal(false);

async function respond() {
  if (replying()) return;
  setReplying(true);
  try {
    await doTheThing();
  } finally {
    setReplying(false);
  }
}
原因

单个 busy() 布尔值会导致死锁:

  • 长时间运行的任务设置 busy(true)
  • 出现权限提示,其按钮被 busy() 禁用
  • 任务必须等到权限获得答复才能继续
  • 用户无法答复,因为按钮已被禁用

解决方案:权限 UI 只能由 专用于权限的 pending 状态控制是否禁用。

异步处理器中的信号快照

如果在异步函数中读取信号,并且需要稳定的值,请尽早创建快照:

const request = activePermission();
if (!request) return;
const requestID = request.id;

await respondPermission(requestID, "always");

派生 UI 状态

对于计算得出的禁用状态,优先使用 createMemo():

const canSend = createMemo(() => prompt().trim().length > 0 && !busy());

列表

  • 使用 setter 回调进行派生更新:
setItems((current) => current.filter((x) => x.id !== id));
  • 不要原地修改 current。

实用检查清单(SolidJS UI 更改)

  • 是否有按钮依赖于一个可能在长时间运行的工作期间为真的全局标志?
  • 两个异步操作是否可能重叠,并争用同一个布尔值?
  • 是否有重复的 UI 状态(能否改为派生状态)?
  • 事件处理器是否在 await 之后读取信号,而此时值可能已经改变?
  • 如果重构了 props 或类型,是否更新了所有中间组件的签名和调用位置?

参考资料

评论

支持 Markdown