React onSetstate函数被多次调用



嗨,我在React中有这个组件,当输入字段值改变时,这个组件的目的是将该值存储在messageIput state variable中,当用户开始键入时,我调用handleMessagePressprinting composing,并等待五秒钟,如果用户仍然键入后,我再次输入printing composing,如果用户停止键入,那么我调用handleChangeprints paused。但是现在的问题是,当我在messageIput state variable中设置值时,它再次打印排版。下面的代码片段是如何工作的,我想在我的react组件

const { useRef, useState } = React;
const DEBOUNCE_THRESHOLD = 5000;
function App() {
const [messageInput, setMessageInput] = useState("");
const timeoutHandler = useRef(null);
let executeHandlePress = true;
const handleChange = (event) => {
if (timeoutHandler.current) {
clearTimeout(timeoutHandler.current);
}
timeoutHandler.current = setTimeout(() => {
console.log("paused");
}, DEBOUNCE_THRESHOLD);
};
const handleMessagePress = (e) => {
if (!executeHandlePress) {
// if flag false, return
return;
} else {
console.log("composing"); // if true execute
executeHandlePress = false; // toggle flag to false
setTimeout(() => {
executeHandlePress = true; // reset after 5 seconds
}, DEBOUNCE_THRESHOLD);
}
};
const handleMessageChange = (message) => {
setMessageInput(message);
};
const handleMessagePress1 = (e) => {
if (e.key === "Enter" || e === "send") {
console.log("sendMessage");
}
};
return (
<React.Fragment>
<input
value={messageInput}
type="text"
id="messageInputField"
placeholder="Write your message..."
onKeyPress={(e) => {
handleMessagePress(e);
handleMessagePress1(e);
}}
onChange={(e) => {
handleMessageChange(e.target.value);
handleChange();
}}
/>
</React.Fragment>
);
}
ReactDOM.render(<App />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.0/umd/react-dom.production.min.js"></script>

//js中的工作代码

let myInput = document.getElementById("messageInputField");
let timer;
let executeHandlePress = true; // flag to watch handle press function execution
if (myInput) {
myInput.addEventListener("keyup", () => {
clearTimeout(timer);
timer = setTimeout(stop, 5000);
});
}
const stop = () => {
console.log("user stop typing");
}
const handleMessagePress = (e) => {
if (!executeHandlePress) { // if flag false, return
return;
}
console.log("user is typing"); // if true execute
executeHandlePress = false; // toggle flag to false
setTimeout(() => {
executeHandlePress = true; // reset after 5 seconds
}, 5000);
}
<input placeholder="type your message" id="messageInputField" onKeyPress=" handleMessagePress(event)" />

当你在React中设置state时,它会导致你的组件函数被再次调用来重新渲染组件。每次渲染时,你都在重置executeHandlePress,因为它在这里被重新声明:

let executeHandlePress = true;
因此,无论您在这个特定的快照/呈现中对这个变量做了什么,都不会在下一次呈现中持续存在,因为它将被重新声明。为了帮助处理这个问题,你可以创建一个ref:
const executeHandlePress = useRef(true);

这样你的布尔值将在多次渲染中持续存在。当使用ref时,您可以使用executeHandlePress.current:

来引用布尔值。

const { useRef, useState } = React;
const DEBOUNCE_THRESHOLD = 5000;
function App() {
const [messageInput, setMessageInput] = useState("");
const timeoutHandler = useRef(null);
const executeHandlePress = useRef(true);
const handleChange = (event) => {
if (timeoutHandler.current) {
clearTimeout(timeoutHandler.current);
}
timeoutHandler.current = setTimeout(() => {
console.log("paused");
}, DEBOUNCE_THRESHOLD);
};
const handleMessagePress = (e) => {
if (executeHandlePress.current) {
console.log("composing"); // if true execute
executeHandlePress.current = false; // toggle flag to false
setTimeout(() => {
executeHandlePress.current = true; // reset after 5 seconds
}, DEBOUNCE_THRESHOLD);
}
};
const handleMessageChange = (message) => {
setMessageInput(message);
};
const handleMessagePress1 = (e) => {
if (e.key === "Enter" || e === "send") {
console.log("sendMessage");
}
};
return (
<React.Fragment>
<input
value={messageInput}
type="text"
id="messageInputField"
placeholder="Write your message..."
onKeyPress={(e) => {
handleMessagePress(e);
handleMessagePress1(e);
}}
onChange={(e) => {
handleMessageChange(e.target.value);
handleChange();
}}
/>
</React.Fragment>
);
}
ReactDOM.render(<App />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.0/umd/react-dom.production.min.js"></script>

最新更新