我使用的反应版本是:
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
这是下拉菜单的一些简单代码。
codesandbox 链接:https://codesandbox.io/s/sad-firefly-sphup6?file=/src/App.tsx
import { MouseEvent, useEffect, useState } from 'react';
import type { ReactNode } from 'react';
type DropdownProps = {
target: HTMLElement | null;
children: ReactNode;
};
function Dropdown({ target, children }: DropdownProps) {
useEffect(() => {
if (!target) return;
const listener = () => {
console.log('listener executed');
};
document.addEventListener('click', listener);
return () => document.removeEventListener('click', listener);
}, [target]);
if (!target) {
return null;
}
return <div>{children}</div>;
}
function App() {
const [target, setTarget] = useState<HTMLButtonElement | null>(null);
return (
<div>
<button
onClick={(e: MouseEvent<HTMLButtonElement>) =>
setTarget(e.currentTarget)
}
>
Button
</button>
<Dropdown target={target}>dropdown test</Dropdown>
</div>
);
}
export default App;
这里,当第一次按下按钮时,一个事件会附加到文档中,并且监听器会立即执行。
我期望的行为是第一次按下按钮时,事件将附加到文档,下次按下按钮时,侦听器将触发。
但实际上,一旦第一次按下按钮,事件侦听器就会触发。
使用React 17的ReactDom.render时不会出现此问题,但使用18的createRoot时会出现问题。
这似乎是与下面链接中的问题类似的问题
使用 useState 的弹出窗口在 React 18 中停止工作
我想知道为什么这在 React 18 中不起作用。
我认为这是因为React新的并发渲染机制。
我设法使用 useDeferredValue 解决了这个问题
https://codesandbox.io/s/fervent-frog-clj1wi?file=/src/App.tsx