如何解决如何使反应钩子与 ref 保持一致
我想使用自定义钩子切换输入元素。
这是我的自定义钩子:
import { RefObject,useEffect } from "react";
export const useEscape = (
ref: RefObject<HTMLElement>,triggerFn: () => void
) => {
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (ref.current && !ref.current.contains(event.target as Node)) {
triggerFn();
}
};
document.addEventListener("click",handleClickOutside);
return () => window.removeEventListener("click",handleClickOutside);
});
};
以及使用钩子的示例
import * as React from "react";
import "./styles.css";
import { useEscape } from "./useEscape";
export default function App() {
const [showInput,setShowInput] = React.useState(false);
const inputRef = React.useRef(null);
useEscape(inputRef,() => {
if (showInput) setShowInput(false);
});
return (
<div>
{showInput && (
<input ref={inputRef} placeholder="click outside to toggle" />
)}
{!showInput && (
<span
style={{ border: "1px solid black" }}
onClick={() => {
console.log("toggle to trigger");
setShowInput(true);
}}
>
click to toggle input
</span>
)}
</div>
);
}
这是代码和盒子演示的 link。
问题来了。在我点击 span
元素切换到输入状态后。在 input 元素外单击后,它将永远无法再次切换回 input 状态。
我想我知道为什么会这样。 react ref 仍然指向最初创建的 input
元素。然而,当反应切换到显示 span
状态时,它会卸载 input
元素,并且我的自定义钩子永远不会与新的 input
元素的 React 同步。如何自定义我的 useEscape
钩子,以便 react ref 同步? (顺便说一下,我不想使用样式作为在视觉上“隐藏”输入元素的解决方法)。
解决方法
import { RefObject,useEffect } from "react";
export const useEscape = (
ref: RefObject<HTMLElement>,triggerFn: () => void
) => {
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (ref.current && !ref.current.contains(event.target as Node)) {
triggerFn();
}
};
document.addEventListener("click",handleClickOutside);
return () => document.removeEventListener("click",handleClickOutside);
},[ref,triggerFn]);
};
你的整个逻辑是绝对正确的。有一个轻微的错误,而不是 window.removeEventListener,改成document.removeEventListener。
您正在删除导致错误的全局窗口对象上的事件侦听器。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。