当我尝试从 React Hook 中获取示例时,我遇到了有关useState
的问题。
在下面的代码中,单击按钮时,我为document
添加事件并检查count
的值。我的期望是count
console.log
并查看相同的内容。但实际上,我在console
中获得了旧值(初始化值(,并在视图中获得了新值。我不明白为什么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;
document.addEventListener 捕获组件外部的事件,则需要使用 useEffect
挂钩添加事件,然后可以使用useState
来确定是否捕获。
请注意,在我传递[capture]
useEffect
中,这将使 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>
理解你的例子,但是当我申请时会感到困惑。在起源上,我总是调用函数是handleClick
,并且在运行handleClickOutside
后仍然调用它,但现在我不知道如何使用钩子应用它。
这是我想要的代码而不是钩子
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