窗口.addEventListener用React冻结浏览器



这是我第一次使用React,我不明白为什么这段代码在多次点击窗口时就像冻结浏览器(我使用Chrome)

import "./App.css";
import { useState } from "react";
function App() {
const [window_touched, setWindow_thouched] = useState(0);
window.addEventListener("click", () =>
setWindow_thouched(window_touched + 1)
);
return (
<div className="App">
{`This window has been thouched ${window_touched} times`}
</div>
);
}
export default App;

每次都执行函数组件的主体呈现组件。你不断地添加额外的事件处理程序,从来没有清理旧的。

相反,在组件被挂载时添加一次处理程序,并在组件被卸载时删除它,使用useEffectcallback与空依赖项数组和清理回调:

function App() {
const [window_touched, set_window_touched] = useState(0);
useEffect(() => {
const handler = () => {
set_window_touched((touched) => touched + 1);
};
window.addEventListener("click", handler);
return () => {
// This is the cleanup function
window.removeEventListener("click", handler);
};
}, []);
return (
<div className="App">
{`This window has been touched ${window_touched} times`}
</div>
);
}

(我使用名称set_window_touched而不是setWindow_thouched,因为A)我想修复拼写错误,B)一致地使用snake_case。但是请注意,通常的约定是使用windowTouchedsetWindowTouched。)

注意,它使用了set_window_touched的回调版本,传递了一个更新函数,该函数接收set_window_touched的最新版本并返回要设置的新值。这是因为处理程序只在组件挂载的第一个时间创建,这意味着如果它直接使用window_touched,它只会看到第一次调用App时的值,该值始终是0

生活的例子:

const { useState, useEffect } = React;
function App() {
const [window_touched, set_window_touched] = useState(0);
useEffect(() => {
const handler = () => {
set_window_touched((touched) => touched + 1);
};
window.addEventListener("click", handler);
return () => {
// This is the cleanup function
window.removeEventListener("click", handler);
};
}, []);
return (
<div className="App">
{`This window has been touched ${window_touched} times`}
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>


旁注:比起模板文字,在React中包含带有占位符的文本的更标准的方式是在JSX中:

return (
<div className="App">
This window has been touched {window_touched} times
</div>
);

生活的例子:

const { useState, useEffect } = React;
function App() {
const [window_touched, set_window_touched] = useState(0);
useEffect(() => {
const handler = () => {
set_window_touched((touched) => touched + 1);
};
window.addEventListener("click", handler);
return () => {
// This is the cleanup function
window.removeEventListener("click", handler);
};
}, []);
return (
<div className="App">
This window has been touched {window_touched} times
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

相关内容

  • 没有找到相关文章

最新更新