React组件报错TypeError:无法读取null的value属性及输入值异常
问题分析与解决方案
核心问题原因
- Ref引用混乱:你定义了内部
inputRef但未绑定到输入框,反而让输入框直接使用props.innerRef,同时在useEffect中将未绑定的inputRef.current(值为null)赋值给props.innerRef.current,导致父组件通过innerRef访问输入框时拿到null,触发Cannot read properties of null (reading 'value')错误。 - 输入框受控状态与外部ref冲突:输入框是受控组件(绑定了
inputValue状态),直接将外部ref绑定到输入框可能导致外部操作干扰内部状态,引发显示异常。
修复步骤
- 将输入框的ref绑定到组件内部的
inputRef,确保内部ref能正确指向输入框元素。 - 保留
useEffect中向props.innerRef传递内部ref的逻辑,让父组件仍能通过innerRef访问输入框,同时避免覆盖输入框的原始ref引用。 - 合并键盘事件逻辑,移除重复的
onKeyPress处理,简化代码。
修改后的完整代码
import { useState, useRef, useEffect } from "react"; const SkillsInput = (props) => { const [tags, setTags] = useState(props.tags.split(", ")); const [inputValue, setInputValue] = useState(''); const inputRef = useRef(null); useEffect(() => { if (props.innerRef) { props.innerRef.current = inputRef.current; } }, [props.innerRef]); const removeTags = (indexToRemove) => { const updatedTags = [...tags]; updatedTags.splice(indexToRemove, 1); setTags(updatedTags); props.selectedTags(updatedTags); }; const addTags = (event) => { if (event.key === "Enter") { event.preventDefault(); // 统一处理阻止默认行为 if (inputValue.trim() !== "") { const newTag = inputValue; const newTags = [...tags, newTag]; setTags(newTags); props.selectedTags(newTags); setInputValue(''); } } }; return ( <div className='form-control w-full my-2'> <label className='label'> <span className='label-text text-dark dark:text-lightOne text-base capitalize'> {props.name} </span> </label> <div className="flex items-center flex-wrap input input-bordered h-auto bg-main-bg dark:bg-main-dark-bg"> <div className='flex flex-wrap justify-start items-center'> {tags.map((tag, index) => ( <li key={index} className='w-auto h-8 flex justify-center items-center text-white px-2 text-sm rounded-md bg-main my-2 mr-2' > <span>{tag}</span> <span className='block w-5 h-5 leading-4 text-center text-md ml-2 text-main rounded-full bg-lightOne cursor-pointer font-bold' onClick={() => removeTags(index)} > x </span> </li> ))} </div> <input ref={inputRef} // 绑定内部ref name={props.name} type='text' className='bg-main-bg dark:bg-main-dark-bg outline-none my-2 flex-1' value={inputValue} onChange={(e) => setInputValue(e.target.value)} onKeyUp={addTags} placeholder='Press enter to add tags' /> </div> </div> ); }; export default SkillsInput;
额外说明
- 修复后,输入框的受控状态(
inputValue)会正常更新,不会再出现值为null的情况。 - 父组件通过
innerRef仍能正常访问输入框元素,同时不会干扰内部受控状态的逻辑。 - 合并了键盘事件的
preventDefault处理,避免重复逻辑,代码更简洁。
内容的提问来源于stack exchange,提问作者akechi17
相关产品推荐
相关产品推荐

