HOOK组件内使用useRef作用于隐藏的Input为什么会导致ref失效?

duxingren
  • 6

https://preview.pro.ant.desig...
v4预览版,【个人中心】 菜单栏下,【标签】这个组件,后边那个+图标点击之后Input没有自动获取到焦点,所以导致失去焦点隐藏Input也失效,必须手动获取下焦点在失去才有效. v2版本没有问题

📷 复现步骤

v4失效:https://preview.pro.ant.desig...

v2可以:https://v2-preview-ant-design...
image

💻 复现代码

import { Input, Tag } from 'antd';
import React, { useState, useRef } from 'react';

const TagList: React.FC<{}> = ({ tags }) => {
  const ref = useRef<Input | null>(null);
  const [newTags, setNewTags] = useState([]);
  const [inputVisible, setInputVisible] = useState<boolean>(false);
  const [inputValue, setInputValue] = useState<string>('');

  const showInput = () => {
    setInputVisible(true);
    if (ref.current) {
      console.log(ref.current);  // 这里打印ref.current为null
      ref.current?.focus();
    }
  };

  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setInputValue(e.target.value);
  };

  const handleInputConfirm = () => {
    let tempsTags = [...newTags];
    if (inputValue && tempsTags.filter((tag) => tag.label === inputValue).length === 0) {
      tempsTags = [...tempsTags, { key: `new-${tempsTags.length}`, label: inputValue }];
    }
    setNewTags(tempsTags);
    setInputVisible(false);
    setInputValue('');
  };

  return (
    <div>
      <div>标签</div>
      {(tags || []).concat(newTags).map((item) => (
        <Tag key={item.key}>{item.label}</Tag>
      ))}
      {inputVisible && (
        <Input
          ref={ref}
          type="text"
          size="small"
          style={{ width: 78 }}
          value={inputValue}
          onChange={handleInputChange}
          onBlur={handleInputConfirm}
          onPressEnter={handleInputConfirm}
        />
      )}
      {/* 点击时隐藏此按钮,并打开Input,同时自动获取到焦点, 但此时Input自动获取焦点失败  */}
      {!inputVisible && (
        <Tag onClick={showInput} style={{ borderStyle: 'dashed' }}>
          <PlusOutlined />   
        </Tag>
      )}
    </div>
  );
};

请问是什么原因,应该注意什么?

我想应该是 Input组件放在判断里边,初始为false,所以input初始没有渲染, 但是点击显示时,为什么ref会失效呢?

© 版本信息

  • Ant Design Pro 版本: [e.g. 4.0.0]
  • umi 版本
  • 浏览器环境
  • 开发环境 [e.g. mac OS]
回复
阅读 783
2 个回答

// hooks 执行时异步操作,当你设置显示input之后,有立马执行获取焦点操作,肯定会出问题,试试下面的操作

 useEffect(()=>{
    if(inputVisible && ref.current) {
        console.log(ref.current);
        ref.current?.focus();
    }
 },[inputVisible])
 const showInput = () => {
    setInputVisible(true);
  };
  

在github上得到了一个答案是可行的,而且还很简单

setInputVisible(true);执行之后,组件并不会立即重新渲染,而是会继续执行剩下的语句,所以ref.current的值仍然是null,你的那个log应该是打印不出来的。
Input添加autoFocus应该可以在渲染的时候自动获取焦点

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
你知道吗?

宣传栏