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

React中传递useRef给子组件为何未报错且正常运行?

为什么把useRef作为props传给子组件没报错还能正常运行?

我是React新手,得知将useRef()作为props传递给子组件并非正确方式,但为何该写法没有报错且能正常运行?相关代码如下:

const App = () => {
    const todoRef = useRef(null);
    const [todos, setTodos] = useState([]);
    const onFormSubmit = (e) => {
        e.preventDefault();
        const todo = todoRef.current.value;
        if (todo.trim().length > 0) {
            setTodos((prevTodo) => [
                ...prevTodo,
                { title: todo, isCompleted: false },
            ]);
            todoRef.current.value = null;
        }
    };
    return (
        <div>
            <h1>Todos</h1>
            <InputField onFormSubmit={onFormSubmit} todoRef={todoRef} />
            <TodoList todos={todos} />
        </div>
    );
};
const InputField = ({ onFormSubmit, todoRef }) => {
    return (
        <form onSubmit={onFormSubmit}>
            <input
                type="text"
                name="task"
                placeholder="What task needs to be completed?"
                ref={todoRef}
            />
        </form>
    );
};

原因解析

首先,React本身不会禁止你把ref作为props传递,它只是不符合React推荐的数据流规范。useRef创建的是一个普通的JavaScript对象,结构就是{ current: ... },本质上和传递普通对象props没区别,所以React不会抛出错误,子组件也能正常接收并绑定到input上。

那为什么这种写法不推荐?核心问题有几点:

  • 破坏组件封装性:子组件InputField本该自己管理输入框的状态,现在父组件直接通过ref操控它的DOM元素,子组件的内部实现被父组件耦合,后续修改InputField结构(比如替换input组件)会导致父组件代码失效。
  • 违背单向数据流:React推荐数据从父到子通过props传递,状态变化通过回调通知父组件。直接用ref操作DOM属于绕开数据流的写法,代码会更难追踪和维护。
  • 易混淆ref的用途:ref的设计初衷是访问DOM或组件实例,不是用来传递状态,这种写法会让你错误理解ref的正确使用场景。

规范写法示例

让子组件自己管理输入状态,通过回调把值传给父组件:

const App = () => {
    const [todos, setTodos] = useState([]);
    const onFormSubmit = (todo) => {
        if (todo.trim().length > 0) {
            setTodos((prevTodo) => [
                ...prevTodo,
                { title: todo, isCompleted: false },
            ]);
        }
    };
    return (
        <div>
            <h1>Todos</h1>
            <InputField onFormSubmit={onFormSubmit} />
            <TodoList todos={todos} />
        </div>
    );
};

const InputField = ({ onFormSubmit }) => {
    const [inputValue, setInputValue] = useState('');
    const handleSubmit = (e) => {
        e.preventDefault();
        onFormSubmit(inputValue);
        setInputValue('');
    };
    return (
        <form onSubmit={handleSubmit}>
            <input
                type="text"
                name="task"
                placeholder="What task needs to be completed?"
                value={inputValue}
                onChange={(e) => setInputValue(e.target.value)}
            />
        </form>
    );
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 14:43:35