reactjs - React useEffect 缺少依赖错误,但它在那里
问题描述
我有这个组件,我正在使用 useRef 和 useEffect 来处理弹出窗口外的点击,以便我可以关闭它。
我添加了 useEffect 需要的两个依赖项,但出现此错误:
The 'handleClickOutside' function makes the dependencies of useEffect Hook (at line 117) change on every render. Move it inside the useEffect callback. Alternatively, wrap the 'handleClickOutside' definition into its own useCallback()
正如您在此处看到的,我添加了两个依赖项,但它仍然会引发此错误/警告:
useEffect(() => {
if (isOverlayOpen) {
document.addEventListener("mousedown", handleClickOutside);
} else {
document.removeEventListener("mousedown", handleClickOutside);
}
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [isOverlayOpen, handleClickOutside]);
任何想法如何解决这一问题?
这里是代码框: https ://codesandbox.io/s/laughing-newton-1gcme ?fontsize=14&hidenavigation=1&theme=dark 问题出在 src/components/typeahead 第 100 行
这里是组件代码:
function ResultsOverlay({
isOpen,
items,
selectItem,
highlightedOption,
setIsOverlayOpen,
isOverlayOpen
}) {
const node = useRef();
const handleClickOutside = e => {
if (node.current.contains(e.target)) {
return;
}
setIsOverlayOpen(false);
};
useEffect(() => {
if (isOverlayOpen) {
document.addEventListener("mousedown", handleClickOutside);
} else {
document.removeEventListener("mousedown", handleClickOutside);
}
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [isOverlayOpen]);
function matchedOptionsClass(index) {
if (highlightedOption === index) {
return "ph4 list f3 sesame-red list-item pointer";
}
return "ph4 list sesame-blue list-item pointer";
}
if (isOpen) {
return (
<div className="absolute" ref={node}>
<ul className="w5 mt0 pa0 h5 overflow-scroll shadow-5 dib">
{items &&
items.map((item, index) => (
<li
onClick={() => selectItem(item)}
className={matchedOptionsClass(index)}
>
{item}
</li>
))}
</ul>
</div>
);
} else {
return null;
}
}
解决方案
两个问题:
首先,做 linst 告诉你的事情,把你的函数定义移动到你的效果中
useEffect(() => {
const handleClickOutside = e => {
if (node.current.contains(e.target)) {
return;
}
setIsOverlayOpen(false);
};
if (isOverlayOpen) {
document.addEventListener("mousedown", handleClickOutside);
} else {
document.removeEventListener("mousedown", handleClickOutside);
}
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [isOverlayOpen]);
其次,setIsOverlayOpen
是通过 提供的回调props
,因此它没有稳定的签名并在每次渲染时触发效果。
假设这setIsOverlayOpen
是一个 setteruseState
并且不需要更改它的签名,您可以通过使用将处理程序包装在附加的依赖检查层中来解决此问题useCallback
const stableHandler = useCallback(setIsOverlayOpen, [])
useEffect(() => {
const handleClickOutside = e => {
if (node.current.contains(e.target)) {
return;
}
stableHandler(false);
};
if (isOverlayOpen) {
document.addEventListener("mousedown", handleClickOutside);
} else {
document.removeEventListener("mousedown", handleClickOutside);
}
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [isOverlayOpen, stableHandler]);
推荐阅读
- latex - 如何在 MNRAS LATEX 纸上添加子图?
- java - Swing MouseMoved 事件是否按输入顺序调度?
- python - ipython交互模式下函数的回声是什么?
- r - R中多项式GLM的SE逆估计(投资者:投资)
- reactjs - Azure Linux Web 应用程序上的下一个 js 应用程序 - 读取目录时出现错误 eisdir 非法操作
- reactjs - 为什么 setState 方法的简单使用在 componentDidMount() 方法中不起作用
- database - CQL 查询以获取 CassandraDB 的 LIST DATATYPE 中的元素计数?
- r - 你如何迭代 R 包的元素?
- python - 如何在 Jupyter Notebook 中授予文件处理访问权限?[权限被拒绝错误]
- javascript - 平滑的进度条