[英]How to stop the infinite loop inside this React useEffect?
I want React to render key presses from a non-React context, more specifically the string array keys
:我希望 React 从非 React 上下文呈现按键,更具体地说是字符串数组
keys
:
import * as React from "react";
import { render } from "react-dom";
let keys: string[] = [];
function handleKeypress(event: any) {
keys.push(event.key);
console.log(keys);
// there will be more code here unrelated to React.
}
document.removeEventListener("keypress", handleKeypress);
document.addEventListener("keypress", handleKeypress);
function App() {
const [keysState, setKeysState] = React.useState<string[]>([]);
React.useEffect(() => {
function updateKeysState() {
setKeysState([...keys]);
}
// if you uncomment this, the code inside useEffect will run forever
// updateKeysState()
console.log("Hello world");
}, [keysState]);
return (
<div>
{keys.map((key: string, id) => (
<li key={id}>{key}</li>
))}
</div>
);
}
const rootElement = document.getElementById("root");
render(<App />, rootElement);
I almost accomplished that... the problem is, the code inside React.useEffect
runs in an infinite loop.我几乎完成了……问题是,
React.useEffect
中的代码在无限循环中运行。
I thought passing [keysState]
as a second argument to React.useEffect
would stop the infinite loop.我认为将
[keysState]
作为第二个参数传递给React.useEffect
会停止无限循环。 But it didn't.但它没有。
Why is this and how to fix it?为什么会这样以及如何解决?
Live code: https://codesandbox.io/s/changing-props-on-react-root-component-forked-eu16oj?file=/src/index.tsx实时代码: https://codesandbox.io/s/changing-props-on-react-root-component-forked-eu16oj?file=/src/index.tsx
The best way would be to integrate the non-React code into the App, so that setting state as a result of a keypress is natural and trivial.最好的方法是将非 React 代码集成到应用程序中,这样设置 state 作为按键的结果是自然而微不足道的。
function App() {
const [keys, setKeys] = React.useState<string[]>([]);
useEffect(() => {
function handleKeypress(event: KeyboardEvent) {
setKeys([...keys, event.key]);
// There will be more code here that's unrelated to React.
}
document.addEventListener("keypress", handleKeypress);
return () => {
document.removeEventListener("keypress", handleKeypress);
};
}, []);
Then you can drop your current React.useEffect
(and its infinite loop) entirely.然后你可以完全放弃你当前的
React.useEffect
(和它的无限循环)。
If that's not an option, you'd have to trigger the React state setter from outside of React - any way you look at it, that'll be pretty ugly.如果这不是一个选项,您将不得不从 React 外部触发 React state setter - 无论您怎么看,这都会非常难看。 I suppose you could assign it to an outside variable:
我想你可以将它分配给一个外部变量:
let setKeysOuter;
function handleKeypress(event: KeyboardEvent) {
setKeysOuter?.(keys => [...keys, event.key]);
// There will be more code here that's unrelated to React.
}
function App() {
const [keys, setKeys] = React.useState<string[]>([]);
setKeysOuter = setKeys;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.