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

React中如何使用useRef在初始渲染后更新input defaultValue

问题原因

React中非受控组件的defaultValue属性仅在组件首次挂载时生效,作用是初始化输入框的值,后续组件重渲染时如果defaultValue发生变化,React不会主动同步更新已经挂载的输入框的实际值。你的代码中输入框始终没有被卸载重挂,所以只有第一次点击编辑时的初始化值能生效,后续切换编辑条目时值不会更新。

这个需求完全可以仅通过useRef实现,不需要改成受控组件,也不需要用placeholder降级交互效果。

可行实现方案

方案1:通过ref直接操作输入框赋值(推荐,完全符合非受控+useRef要求)

非受控组件的核心逻辑就是直接操作DOM,你可以在触发编辑动作时,拿到待编辑的条目内容后,直接通过ref给输入框的value属性赋值,不需要依赖defaultValue的响应式更新。

核心修改点:

  1. 调整editItem方法,在设置编辑状态后直接通过ref给输入框赋值、聚焦
  2. 提交表单后,通过ref手动清空输入框内容——原代码中修改局部变量nameValue的写法是无效的,不会改动输入框的实际显示值

修改后的核心代码如下:

const editItem = (id) => {
  const targetItem = list.find((item) => item.id === id);
  setItemToEdit(targetItem);
  setIsEditing(true);
  // 直接操作DOM给输入框填充待编辑内容
  refContainer.current.value = targetItem.name;
  refContainer.current.focus();
};

const handleSubmit = (e)=>{
  e.preventDefault();
  const nameValue = refContainer.current.value.trim();
  if (!nameValue) return; // 增加空值校验,避免提交空内容
  if (isEditing){
    setList(list.map((item)=>{
      if (item.id === itemToEdit.id){
        return {...item, name: nameValue};
      }
      return item;
    }));
  }
  else {
    const newItem = {
      // 修复原代码bug:Date对象没有getItem方法,用getTime生成时间戳id
      id: new Date().getTime().toString(),
      name: nameValue,
    }
    setList([...list, newItem])
  }
  // 提交后清空输入框,重置编辑状态
  refContainer.current.value = "";
  setIsEditing(false);
}

输入框部分保留简单的默认值设置即可,不影响功能:

<input type="text" ref={refContainer} defaultValue="" />

方案2:给输入框加key触发重挂载(备选)

如果你不想手动操作输入框的value,可以给输入框绑定一个随编辑目标变化的key属性,React会在key变化时自动卸载旧输入框、挂载新输入框,这时候defaultValue就会重新初始化生效:

<input 
  type="text" 
  ref={refContainer} 
  // 编辑时绑定当前条目id,新建状态用固定key
  key={isEditing ? `edit-${itemToEdit.id}` : 'create'}
  defaultValue={isEditing ? itemToEdit.name : ""}
/>

注意:这个方案每次切换编辑目标都会销毁重建输入框,性能略差,属于取巧实现,更推荐第一种直接操作ref的方案。

关于placeholder的说明

完全不需要用placeholder替代。placeholder是浅灰色的提示文本,用户很容易混淆提示内容和实际输入内容,交互体验很差,用上面两种方案都可以实现正常的待编辑内容填充效果。

原代码其他注意点
  • 你当前代码中调用了deleteItem方法但没有实现,需要补充对应的删除逻辑,删除时通过setList过滤掉对应id的条目即可
  • 本地存储读取的getLocalStorage方法需要加异常捕获,避免JSON.parse解析损坏的本地数据导致页面报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 16:18:20