You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Preact Signals修改输入值时自动恢复默认值问题求助

问题原因及解决方案

核心问题是组件每次渲染时都会重新创建state信号,导致修改后的值被立刻重置为初始值。

组件函数每次执行(比如父组件更新、自身状态变化触发重渲染)时,函数内部的代码会从头运行一遍。你直接在组件内用signal()创建的信号,每次都会被重新初始化为{ reps:10, weight:20 },所以修改后的值会被新创建的信号覆盖,看起来像是“立刻恢复”。

修复方案

使用Preact Signals提供的useSignal Hook替代直接调用signal(),它能让信号在组件多次渲染之间保持状态:

  1. 导入useSignal和computed:
import { useSignal, computed } from "@preact/signals";
  1. 将state的创建改为useSignal:
const state = useSignal({
  reps: 10,
  weight: 20,
});
  1. 模板中访问信号值时,可以直接用state.reps(而非state.value.reps),Preact会自动跟踪信号依赖:
// 输入框value改为
value={state.reps}
// 计算值volume的访问简化
<span class="">{volume}</span>

修改后的完整代码

import { useSignal, computed } from "@preact/signals";

export default function SetInput({ setNo }: { setNo: number }) {
  const state = useSignal({
    reps: 10,
    weight: 20,
  });

  const volume = computed(() => state.value.reps * state.value.weight);

  const onHandleChange = (event: any) => {
    const { name, value } = event.target;
    state.value = { ...state.value, [name]: parseInt(value) };
    console.log(name, value, state.value.reps, volume.value);
  };

  return (
    <div class="flex flex-row gap-8 mx-auto">
      <div>
        <label
          htmlFor={`s${setNo}-reps`}
          class="block text-md text-gray-400 opacity-85 mb-2"
        >
          Reps
        </label>
        <input
          name="reps"
          type="number"
          id={`s${setNo}-reps`}
          value={state.reps}
          class="shadow appearance-none border w-24 rounded py-2 px-3 text-gray-700"
          onChange={onHandleChange}
        />
      </div>
      <div>
        <label
          htmlFor={`s${setNo}-weight`}
          class="block text-md text-gray-400 opacity-85 mb-2"
        >
          Weight
        </label>
        <input
          name="weight"
          type="number"
          id={`s${setNo}-weight`}
          value={state.weight}
          class="shadow appearance-none border w-24 rounded py-2 px-3 text-gray-700"
          onChange={onHandleChange}
        />
      </div>
      <div>
        <span
          class="block text-md text-gray-400 opacity-85 mb-2"
        >
          Volume
        </span>
        <span class="">{volume}</span>
      </div>
    </div>
  );
}

另外补充:React/Preact中label的规范属性是htmlFor(驼峰命名),而非html-for,上面代码已一并修正该细节。

内容的提问来源于stack exchange,提问作者ashleytwo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 05:24:55