我正在尝试使用stopPropagation,因此在单击任何其他元素后,我的下拉菜单将关闭。
当我尝试使用stopPropagation &更新一个布尔状态时,按钮重新呈现页面(将状态重置为'false'),而不是将状态更新为true,无论如何它都停留在“true”。
我写了一个例子的代码:
import { useEffect, useState } from "react";
export default function IndexPage() {
const [state, setState] = useState(false);
useEffect(() => {
document.body.addEventListener("click", () => {
setState(false);
});
});
const onButtonClick = (e) => {
e.stopPropagation();
setState(!state);
};
console.log(state);
return (
<div>
<button onClick={onButtonClick}>Click</button>
<h1>{state ? "true" : "false"}</h1>
</div>
);
}
此问题似乎只在Next.js中出现
我用React app写了同样的代码,没有问题。
Next.js codesandbox link
React codesandbox link
编辑:
当你分叉Next.js沙盒项目时,一切都很好(但它并没有解决我原始代码的问题)。
有人知道为什么会这样吗?
2条答案
按热度按时间sxissh061#
这是一个奇怪的问题。在codesandbox容器中,状态被保留以供超时编辑,并且不会导致任何重新渲染,因此可能您的
e.stopPropagation
在添加到事件处理程序时没有触发重新渲染。渲染,因此按钮的旧处理程序仍然附加,这意味着主体上的事件侦听器将在您单击按钮时继续触发,因为我们的处理程序从未更新到factor在e.stopPropagation
中。当我fork你的Next.js设置时,一切正常。因为它现在不是增量更改。容器为我重新构建,不保留任何过去的状态,因此没有陈旧的事件处理程序或任何东西。
测试这两种设置之间差异的最佳方法是查看当您从两者中删除
e.stopPropagation
行时,控制台是否记录任何值。您会看到Next.js没有,但React有。这意味着React的状态即使被保留,仍然会触发render等新的render,创建的事件处理程序知道:嘿,我没有
e.stopPropagation
了,所以我的事件将冒泡更新-Next.js容器似乎每次修改后都需要点击保存进行重新渲染。不要像React容器那样只依赖编辑。
mitkmikd2#
我确实找到了这个bug的修复方法,第一个评论我的人解决了这个问题。
我在代码中添加了一个事件侦听器的清理程序,它似乎解决了这个问题。
在useEffect中进行清理似乎不仅是一个好的实践,而且是“必须的”。
由于清理useEffect重新呈现页面两次而不是三次,它可以防止导致问题的另一次呈现。
非常感谢任何人试图帮助。
固定代码为:
Next.js沙盒link