当我尝试使用React Hook中的示例时,我遇到关于useState
的问题。
在下面的代码中,当单击按钮时,我添加了document
的事件并检查了count
的值。
我的期望是在count
中获得console.log
并以相同的方式查看。但是实际上,我在console
中获得了旧值(初始值),并在view中获得了新值。我无法理解为什么视图中的count
和事件回调中的count
没有变化。
还有一件事情,当我使用setCount(10);
(固定数字)时。然后多次单击按钮(> 2),然后在外部单击,我从checkCount
仅得到2条日志。是React手表count
不变还是下次addEventListener
不变。
import React, { useState } from "react";
function Example() {
const [count, setCount] = useState(0);
const add = () => {
setCount(count + 1);
console.log("value set is ", count);
document.addEventListener("click", checkCount);
};
const checkCount = () => {
console.log(count);
};
return (
<div>
<p>You clicked {count} times</p>
<p>Click button first then click outside button and see console</p>
<button onClick={() => add()}>Click me</button>
</div>
);
}
export default Example;
答案 0 :(得分:0)
如果要使用document.addEventListener捕获组件外部的事件,则需要使用useEffect
钩子添加事件,然后可以使用useState
确定是否捕获是否。
在useEffect
中传递[capture]
的通知,这将使它发生变化,以便useEffect会在此更改时被调用,对此捕获布尔值的简单检查将确定是否添加事件
通过使用useEffect,我们还避免了任何内存泄漏,这也可以解决在卸载组件时也知道要删除事件的情况。
const {useState, useEffect} = React;
function Test() {
const [capture, setCapture] = useState(false);
const [clickInfo, setClickInfo] = useState("Not yet");
function outsideClick() {
setClickInfo(Date.now().toString());
}
useEffect(() => {
if (capture) {
document.addEventListener("click", outsideClick);
return () => {
document.removeEventListener("click", outsideClick);
}
}
}, [capture]);
return <div>
<p>
Click start capture, then click anywhere, and then click stop capture, and click anywhere.</p>
<p>{capture ? "Capturing" : "Not capturing"}</p>
<p>Clicked outside: {clickInfo}</p>
<button onClick={() => setCapture(true)}>
Start Capture
</button>
<button onClick={() => setCapture(false)}>
Stop Capture
</button>
</div>
}
ReactDOM.render(<React.Fragment>
<Test/>
</React.Fragment>, document.querySelector('#mount'));
p { user-select: none }
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="mount"></div>
答案 1 :(得分:0)
@Keith我理解您的示例,但是当我申请时会感到困惑。最初,我总是将函数调用为handleClick
,并且在运行handleClickOutside
之后仍然调用它,但是现在我不知道如何使用钩子将其应用。
这是我要插入的Hook代码
class ClickOutSide extends Component {
constructor(props) {
super(props)
this.wrapperRef = React.createRef();
this.state = {
active: false
}
}
handleClick = () => {
if(!this.state.active) {
document.addEventListener("click", this.handleClickOut);
document.addEventListener("contextmenu", this.handleClickOut);
this.props.clickInside();
} else {
document.removeEventListener("click", this.handleClickOut);
document.removeEventListener("contextmenu", this.handleClickOut);
}
this.setState(prevState => ({
active: !prevState.active,
}));
};
handleClickOut = event => {
const { target } = event;
if (!this.wrapperRef.current.contains(target)) {
this.props.clickOutside();
}
this.handleClick()
}
render(){
return (
<div
onDoubleClick={this.props.onDoubleClick}
onContextMenu={this.handleClick}
onClick={this.handleClick}
ref={this.wrapperRef}
>
{this.props.children}
</div>
)
}
}
export default ClickOutSide