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

React中useRef获取循环渲染input值为空的问题解决

问题:点击Save按钮后newLink输出为空的解决方法

问题原因

你在循环渲染多个<input>时,所有输入框都绑定了同一个link ref。React中,同一个ref被多个DOM元素复用的话,最终只会指向最后一个被渲染的DOM元素。所以当你点击前面的Save按钮时,link.current指向的是最后一个输入框,而非当前按钮对应的那个,自然拿不到正确的值,甚至为空。

解决方案

方案一:使用受控组件(推荐)

用state跟踪每个社交平台的链接,这是React中处理表单输入的标准方式,更易维护和扩展。

import React, { useState } from 'react';
import "./User.css"

export default function User() {
    const objArray = [
        {
            class: "fa fa-envelope",
            title: "Gmail",
            color: "red"
        },
        {
            class: "fa fa-facebook",
            title: "Facebook",
            color: "blue"
        },
        {
            class: "fa fa-instagram",
            title: "Instagram",
            color: "#E4405F"
        },
    ];

    // 初始化state,为每个平台存储链接
    const [links, setLinks] = useState(() => 
        objArray.reduce((acc, item) => {
            acc[item.title] = "";
            return acc;
        }, {})
    );

    // 处理输入框内容变化
    const handleInputChange = (title, value) => {
        setLinks(prev => ({ ...prev, [title]: value }));
    };

    const handleSave = (className, title, color) => {
        const newLink = links[title];
        console.log("this is -> ", className, title, color, newLink);
        // 这里执行保存到firebase的逻辑
    };

    return (
        <main className="User_main">
            <h1>~ Customization ~</h1>
            <h2>Profile Section</h2>
            <br />
            <h2 style={{ marginBottom: "0px" }} > ~ Add Social Media Icons ~ </h2>
            <small>Click and add the social media links</small>
            <br /><br />
            <div className="socialIcons">
                {objArray.map((e) => (
                    <div key={e.title}> {/* 添加key,避免React渲染警告 */}
                        <i style={{ color: `${e.color}`, border: "1px solid " }} className={e.class} />
                        <h4>{e.title}</h4>
                        <input 
                            value={links[e.title]}
                            onChange={(event) => handleInputChange(e.title, event.target.value)}
                            placeholder="Enter link here" 
                            type="url" 
                        />
                        <br />
                        <button onClick={() => handleSave(e.class, e.title, e.color)}>Save</button>
                    </div>
                ))}
            </div>
        </main>
    )
}

方案二:使用ref数组

如果偏好非受控组件,可以创建一个ref数组,让每个输入框对应独立的ref。

import React, { useRef } from 'react';
import "./User.css"

export default function User() {
    const objArray = [
        {
            class: "fa fa-envelope",
            title: "Gmail",
            color: "red"
        },
        {
            class: "fa fa-facebook",
            title: "Facebook",
            color: "blue"
        },
        {
            class: "fa fa-instagram",
            title: "Instagram",
            color: "#E4405F"
        },
    ];

    // 创建ref数组,每个元素对应一个输入框的ref
    const linkRefs = useRef(objArray.map(() => React.createRef()));

    const handleSave = (index, className, title, color) => {
        const newLink = linkRefs.current[index].current.value;
        console.log("this is -> ", className, title, color, newLink);
        // 执行保存到firebase的逻辑
    };

    return (
        <main className="User_main">
            <h1>~ Customization ~</h1>
            <h2>Profile Section</h2>
            <br />
            <h2 style={{ marginBottom: "0px" }} > ~ Add Social Media Icons ~ </h2>
            <small>Click and add the social media links</small>
            <br /><br />
            <div className="socialIcons">
                {objArray.map((e, index) => (
                    <div key={e.title}>
                        <i style={{ color: `${e.color}`, border: "1px solid " }} className={e.class} />
                        <h4>{e.title}</h4>
                        <input 
                            ref={linkRefs.current[index]}
                            placeholder="Enter link here" 
                            type="url" 
                        />
                        <br />
                        <button onClick={() => handleSave(index, e.class, e.title, e.color)}>Save</button>
                    </div>
                ))}
            </div>
        </main>
    )
}

方案对比

  • 方案一(受控组件):符合React单向数据流理念,便于跟踪状态变化,支持表单验证、实时同步等场景,推荐使用。
  • 方案二(ref数组):属于非受控组件,适合简单场景,但状态管理不如受控组件清晰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 16:05:36