React中useRef无法更新输入框值,为什么?

Dev · 竞一 阅读 56

我在做一个表单验证时遇到问题,用useRef获取输入框后,想在失去焦点时更新它的值,但直接赋值好像没生效:


import { useRef, useEffect } from 'react';

function EmailInput() {
  const emailRef = useRef(null);

  const handleBlur = () => {
    // 想自动补全@domain.com后缀
    emailRef.current.value += '@domain.com';
    console.log(emailRef.current.value); // 这里显示正确,但页面没变化
  };

  useEffect(() => {
    emailRef.current.value = '初始值'; // 这里也无法修改初始内容
  }, []);

  return (
    <input 
      ref={emailRef} 
      onBlur={handleBlur} 
      placeholder="输入邮箱"
    />
  );
}

我试过在useEffect里设置初始值,但输入框还是空的。手动修改value后控制台能看到正确值,但页面输入框显示没变化,这是useRef的使用方式有问题吗?

我来解答 赞 5 收藏
二维码
手机扫码查看
1 条解答
司空晓曼
问题出在你直接操作了 DOM 的 value 属性,但 React 的受控组件机制接管了输入框的值。你这样改虽然改了 DOM,但 React 并不知道你改了,所以它后面又把你改的覆盖掉了。

你现在的组件是“非受控组件”写法,却又想用 React 来控制值,这会产生冲突。解决方式有两种:

方式一:彻底使用非受控组件 + useRef
如果你只是想操作 DOM,不想走 React 的状态控制流程,那你可以继续用 useRef,但要确保输入框是“非受控组件”,也就是说不要用 value 属性。那你的写法其实是对的,但在 useEffect 里设置初始值是可以的,说明你可能还是想走受控那一套。

方式二:用 useState 来驱动输入框(推荐)

改一下就行,用 state 控制输入框的值,别直接操作 DOM:

import { useState, useEffect } from 'react';

function EmailInput() {
const [email, setEmail] = useState('');

const handleBlur = () => {
if (!email.endsWith('@domain.com')) {
const newValue = email + '@domain.com';
setEmail(newValue);
}
};

const handleChange = (e) => {
setEmail(e.target.value);
};

useEffect(() => {
setEmail('初始值');
}, []);

return (
<input
type="text"
value={email}
onChange={handleChange}
onBlur={handleBlur}
placeholder="输入邮箱"
/>
);
}


这样写才是 React 的推荐做法,用 state 来驱动 UI,而不是直接操作 DOM。

如果你还想保留 ref,那也建议 ref 只用于 focus、scroll 这类操作,而不是用来改值。React 的状态系统才是更新 UI 的正道。
点赞 2
2026-02-08 11:23