Ant Design可编辑标签组类组件转React函数组件报错问题求助
问题修复方案
错误原因
- 状态丢失问题:函数组件的
useState返回的更新函数不会自动合并剩余状态,你每次仅传入部分状态字段时,其余字段会被直接覆盖丢失,导致state.tags变为undefined,调用map方法时报错。 - setState回调不支持问题:函数组件的状态更新函数不支持类组件
setState的第二个回调参数,你需要通过useEffect监听对应状态变化,来执行状态更新后的后续操作(比如输入框自动聚焦)。 - ref调用错误:通过
useRef创建的引用需要访问.current属性才能拿到对应的DOM实例,原代码中直接调用input.focus()、editInput.focus()会报错。 - 组件导入缺失:原改写代码未导入用到的
Tag、Input、Tooltip组件。
修正后完整代码
import { PlusOutlined } from '@ant-design/icons'; import { useRef, useState, useEffect } from 'react'; import { Tag, Input, Tooltip } from 'antd'; const Tags = () => { const [state, setState] = useState({ tags: ['Unremovable', 'Tag1', 'Tag2', 'Tag3'], inputVisible: false, inputValue: '', editInputIndex: -1, editInputValue: '', }); const inputRef = useRef(null); const editInputRef = useRef(null); // 监听新增标签输入框显示状态,自动聚焦 useEffect(() => { if (state.inputVisible) { inputRef.current?.focus(); } }, [state.inputVisible]); // 监听编辑状态,自动聚焦编辑输入框 useEffect(() => { if (state.editInputIndex !== -1) { editInputRef.current?.focus(); } }, [state.editInputIndex]); const handleClose = removedTag => { const tags = state.tags.filter(tag => tag !== removedTag); setState(prev => ({...prev, tags })); }; const showInput = () => { setState(prev => ({...prev, inputVisible: true })); }; const handleInputChange = e => { setState(prev => ({...prev, inputValue: e.target.value })); }; const handleInputConfirm = () => { const { inputValue, tags } = state; let newTags = [...tags]; if (inputValue && tags.indexOf(inputValue) === -1) { newTags = [...tags, inputValue]; } setState(prev => ({ ...prev, tags: newTags, inputVisible: false, inputValue: '', })); }; const handleEditInputChange = e => { setState(prev => ({...prev, editInputValue: e.target.value })); }; const handleEditInputConfirm = () => { setState(prev => { const newTags = [...prev.tags]; newTags[prev.editInputIndex] = prev.editInputValue; return { ...prev, tags: newTags, editInputIndex: -1, editInputValue: '', }; }); }; const { tags, inputVisible, inputValue, editInputIndex, editInputValue } = state; return ( <> {tags.map((tag, index) => { if (editInputIndex === index) { return ( <Input ref={editInputRef} key={tag} size="small" className="tag-input" value={editInputValue} onChange={handleEditInputChange} onBlur={handleEditInputConfirm} onPressEnter={handleEditInputConfirm} /> ); } const isLongTag = tag.length > 20; const tagElem = ( <Tag className="edit-tag" key={tag} closable={index !== 0} onClose={() => handleClose(tag)} > <span onDoubleClick={e => { if (index !== 0) { setState(prev => ({ ...prev, editInputIndex: index, editInputValue: tag })); e.preventDefault(); } }} > {isLongTag ? `${tag.slice(0, 20)}...` : tag} </span> </Tag> ); return isLongTag ? ( <Tooltip title={tag} key={tag}> {tagElem} </Tooltip> ) : ( tagElem ); })} {inputVisible && ( <Input ref={inputRef} type="text" size="small" className="tag-input" value={inputValue} onChange={handleInputChange} onBlur={handleInputConfirm} onPressEnter={handleInputConfirm} /> )} {!inputVisible && ( <Tag className="site-tag-plus" onClick={showInput}> <PlusOutlined /> 新增标签 </Tag> )} </> ) }; export default Tags;
内容的提问来源于stack exchange,提问作者Dmitry Bochok
相关产品推荐
相关产品推荐

