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

React JS中Copy Text按钮功能异常,请求排查问题

React项目复制文本按钮失效问题排查与修复

问题背景

基于create-react-app开发的项目中,复制文本按钮点击后无反应,控制台报错:

Uncaught TypeError: Cannot read properties of null (reading 'Select')

相关代码如下:

import React, {useState} from 'react'

export default function TextForm(props) {
   
    
    const handleCopy = () => {
        console.log("I am copy");
        let text = document.getElementById("mybox");
        text.Select();
        navigator.clipborad.writetext(text.value);
    }
    
    
    const handleOnChange = (event) =>{
        // console.log("on change");
        setText(event.target.value);
    }
    const [text, setText] = useState('');
  return (
    <>
        <div className='container'>
            <h1>{props.heading} </h1>
            <div className="mb-3">
            <textarea className="form-control" 
            value={text} id="myBox" rows="8" onChange={handleOnChange}></textarea>
            
            <button className="btn btn-primary mx-2 my-2" onClick={handleCopy}>Copy Text</button>
           
            </div>
        </div>
        <div className="container my-3">
            <h2>Your text summary</h2>
            <p>{text.split(" ").length} Word and {text.length} Characters</p>
            <p>{0.008 * text.split(" ").length} Minute Read</p>
            <h3>Preview</h3>
            <p>{text}</p>
        </div>
    </>
  )
}

错误原因

  • ID大小写不匹配:代码中用document.getElementById("mybox")获取元素,但textarea实际ID是myBox(首字母大写),导致获取结果为null,调用Select()时触发报错。
  • 方法名拼写错误:DOM元素的选中方法是select()(小写s),不是Select()(大写S)。
  • Clipboard API拼写错误:navigator.clipborad应为navigator.clipboard,writetext应为writeText(大写T)。
  • 不符合React最佳实践:直接用document.getElementById操作DOM违背React数据流理念,推荐用useRef获取DOM元素。

修复后的代码

import React, { useState, useRef } from 'react'

export default function TextForm(props) {
    // 用useRef获取textarea元素
    const textareaRef = useRef(null);
    
    const handleCopy = () => {
        console.log("I am copy");
        // 先判断元素是否存在
        if (!textareaRef.current) return;
        
        // 选中textarea内容
        textareaRef.current.select();
        // 调用正确的Clipboard API复制文本
        navigator.clipboard.writeText(textareaRef.current.value)
            .then(() => {
                console.log("文本已复制到剪贴板");
                // 复制后取消选中,提升体验
                window.getSelection().removeAllRanges();
            })
            .catch(err => {
                console.error("复制失败:", err);
            });
    }
    
    const handleOnChange = (event) =>{
        setText(event.target.value);
    }
    
    const [text, setText] = useState('');
    
    return (
        <>
            <div className='container'>
                <h1>{props.heading} </h1>
                <div className="mb-3">
                    <textarea 
                        className="form-control" 
                        value={text} 
                        ref={textareaRef} // 绑定ref
                        rows="8" 
                        onChange={handleOnChange}
                    ></textarea>
                    
                    <button className="btn btn-primary mx-2 my-2" onClick={handleCopy}>Copy Text</button>
                </div>
            </div>
            <div className="container my-3">
                <h2>文本摘要</h2>
                {/* 优化单词计数,避免空文本或多空格导致的错误 */}
                <p>{text.trim() ? text.split(/\s+/).length : 0} 个单词,{text.length} 个字符</p>
                <p>{0.008 * (text.trim() ? text.split(/\s+/).length : 0)} 分钟阅读时长</p>
                <h3>预览</h3>
                <p>{text || "请输入文本"}</p>
            </div>
        </>
    )
}

额外优化说明

  • 增加空值判断,防止组件未完全挂载时操作DOM报错。
  • 优化单词计数逻辑:用正则/\s+/分割文本,避免多个连续空格误计为单词;空文本时显示0个单词。
  • 添加复制成功/失败的日志,方便调试。
  • 复制后取消文本选中状态,提升用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 04:45:44