Preact Signals修改输入值时自动恢复默认值问题求助
问题原因及解决方案
核心问题是组件每次渲染时都会重新创建state信号,导致修改后的值被立刻重置为初始值。
组件函数每次执行(比如父组件更新、自身状态变化触发重渲染)时,函数内部的代码会从头运行一遍。你直接在组件内用signal()创建的信号,每次都会被重新初始化为{ reps:10, weight:20 },所以修改后的值会被新创建的信号覆盖,看起来像是“立刻恢复”。
修复方案
使用Preact Signals提供的useSignal Hook替代直接调用signal(),它能让信号在组件多次渲染之间保持状态:
- 导入
useSignal和computed:
import { useSignal, computed } from "@preact/signals";
- 将
state的创建改为useSignal:
const state = useSignal({ reps: 10, weight: 20, });
- 模板中访问信号值时,可以直接用
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
相关产品推荐
相关产品推荐

