|React:useOutsideClick 钩子给出 forwardRef 警告信息

Posted

技术标签:

【中文标题】|React:useOutsideClick 钩子给出 forwardRef 警告信息【英文标题】:|React:useOutsideClick hook gives forwardRef warning message 【发布时间】:2022-01-06 09:44:42 【问题描述】:

我从 firebase 获取数据并将这些数据映射到卡片中,每张卡片都有编辑组件和 CardComponent(编辑组件父级),它们使用 useHandleOpen 自定义钩子提供的 ref

错误信息:

函数组件不能被赋予 refs。尝试访问此 ref 将失败。你的意思是使用 React.forwardRef() 吗?

使用 ref 的组件

export default function EditCard(id) 
  const  ref, isOpen, setIsOpen  = useHandleOpen(false);

  return (
    <div>
      <GoKebabVertical
        ref=ref
        className="cursor-pointer   "
        onClick=() => setIsOpen(true)
      />
      isOpen && (
        <div
          ref=ref
          className="w-20 h-15 bg-white z-30 rounded-md  absolute text-center
        top-0 right-0
        "
        >
          <p className="hover:bg-blue-300 hover:text-white cursor-pointer">
            Edytuj
          </p>
          <p
            className="bg-red-400 text-white font-semibold   hover:bg-red-600 cursor-pointer"
            onClick=() => 
          >
            Usuń
          </p>
        </div>
      )
    </div>
  );


export const Edit = memo(EditCard);

使用 ref tho 及其 Edit 父级的卡片组件

const Card = ( data, id ) => 
  const editRef = useRef(null);

  const  ref, isOpen, setIsOpen  = useHandleOpen(editRef);

  return (
    <div
      className="bg-gradient-to-r from-blue-200 to-purple-500
      w-64 h-28  rounded-md relative
     "
    >
      <div className="relative top-0 left-0">
        <p className="px-2 pt-1 font-bold   text-gray-800 text-lg">
          data.subject_name
        </p>
        <p className="px-2 text-xs   text-gray-800">Sala 101</p>
      </div>
      <div
        className="absolute top-0 right-0 rounded-r-md
        rounded-b-none
      bg-white w-6 h-7
grid place-items-center
      "
      >
        <Edit id=id />
      </div>
      <div className="absolute bottom-9 left-0 mb-2.5">
        <p className="px-2 text-xs   text-gray-800">data.teacher</p>
      </div>
      <div className=" flex direction-row mt-7 text-center  w-full justify-end align-bottom pr-2    ">
        <div className="rounded-lg w-14 h-7 mx-3 bg-purple-300">
          <a
            href=data.link_subject
            className="text-gray-800 
          
          "
            target="_blank"
            rel="noreferrer"
          >
            Lekcja
          </a>
        </div>
        <div className="rounded-lg w-14 h-7 bg-gray-800 ">
          <a
            href=data.link_online_lesson
            target="_blank"
            rel="noreferrer"
            className="text-white"
          >
            Online
          </a>
        </div>
      </div>
      <div
        className=" absolute bottom-0 left-0 rounded-l-md
      bg-white w-7 h-6  grid place-items-center devide-solid"
      >
        isOpen ? (
          <AiOutlineUp
            className="cursor-pointer"
            ref=ref
            onClick=() => setIsOpen(true)
          />
        ) : (
          <AiOutlineDown
            className="cursor-pointer"
            ref=ref
            onClick=() => setIsOpen(true)
          />
        )
      </div>
      isOpen && (
        <div
          className="bg-gradient-to-r from-blue-200 to-purple-500 w-full text-left rounded-b-md p-4 "
          ref=ref
        >
          <p className="font-bold   text-gray-800 text-sm ">Lekcje w:</p>
          <p className="text-gray-800 text-sm">PN: 8-12</p>
        </div>
      )
    </div>
  );
;

export const CardSubject = memo(Card);

带有参考的自定义钩子:

    export default function useHandleOpen() 
      const [isOpen, setIsOpen] = useState(false);
      const ref = useRef(null);
    
      const handleClickOutside = (event) => 
        if (ref.current && !ref.current.contains(event.target)) 
          setIsOpen(!isOpen);
        
      ;
    
      useEffect(() => 
        document.addEventListener("click", handleClickOutside, !isOpen);
    
        return () => 
          document.removeEventListener("click", handleClickOutside, !isOpen);
        ;
      );
    
      return  ref, isOpen, setIsOpen ;
    

编辑:尝试以这种方式更改它,但这也会显示警告。

export default function useHandleOpen(ref) 
  const [isOpen, setIsOpen] = useState(false);

  const handleClickOutside = (event) => 
    if (ref.current && !ref.current.contains(event.target)) 
      setIsOpen(!isOpen);
    
  ;

  useEffect(() => 
    document.addEventListener("click", handleClickOutside, !isOpen);

    return () => 
      document.removeEventListener("click", handleClickOutside, !isOpen);
    ;
  );

  return  ref, isOpen, setIsOpen ;

并像这样使用钩子:

const editRef = useRef(null);

 const  ref, isOpen, setIsOpen  = useHandleOpen(editRef);

【问题讨论】:

在组件中创建 ref 并将其传递给您的钩子。 照你说的做了,但没用 【参考方案1】:

好的,我通过从我使用 onClick 方法更改状态的地方删除 ref 来修复它

【讨论】:

以上是关于|React:useOutsideClick 钩子给出 forwardRef 警告信息的主要内容,如果未能解决你的问题,请参考以下文章

键盘钩子怎么 使用

git自定义项目钩子和全局钩子

对钩子的理解

DELPHI中的钩子是啥?

Vue3 生命周期钩子函数

钩子问题.