【发布时间】:2020-11-23 04:59:38
【问题描述】:
我需要添加一些与 React 之外的对象交互的事件处理程序(以 Google 地图为例)。 在这个处理函数中,我想访问一些可以发送给这个外部对象的状态。
如果我将状态作为依赖项传递给效果,它可以工作(我可以正确访问状态)但是每次状态更改时都会添加添加/删除处理程序。
如果我不将状态作为依赖项传递,则添加/删除处理程序会添加适当的次数(基本上是一次),但状态永远不会更新(或更准确地说,处理程序无法提取最新状态)。
Codepen 示例:
也许最好用 Codepen 来解释: https://codepen.io/cjke/pen/dyMbMYr?editors=0010
const App = () => {
const [n, setN] = React.useState(0);
React.useEffect(() => {
const os = document.getElementById('outside-react')
const handleMouseOver = () => {
// I know innerHTML isn't "react" - this is an example of interacting with an element outside of React
os.innerHTML = `N=${n}`
}
console.log('Add handler')
os.addEventListener('mouseover', handleMouseOver)
return () => {
console.log('Remove handler')
os.removeEventListener('mouseover', handleMouseOver)
}
}, []) // <-- I can change this to [n] and `n` can be accessed, but add/remove keeps getting invoked
return (
<div>
<button onClick={() => setN(n + 1)}>+</button>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
总结
如果效果的 dep 列表是[n],则状态会更新,但每次状态更改都会添加/删除添加/删除处理程序。如果效果的 dep 列表是 [],则添加/删除处理程序可以正常工作,但状态始终为 0(初始状态)。
我想要两者的混合。访问状态,但只访问一次useEffect(好像依赖是[])。
编辑:进一步澄清
我知道如何使用生命周期方法解决它,但不确定如何使用 Hooks。
如果上面是一个类组件,它看起来像:
class App extends React.Component {
constructor(props) {
super(props)
this.state = { n: 0 };
}
handleMouseOver = () => {
const os = document.getElementById("outside-react");
os.innerHTML = `N=${this.state.n}`;
};
componentDidMount() {
console.log("Add handler");
const os = document.getElementById("outside-react");
os.addEventListener("mouseover", this.handleMouseOver);
}
componentWillUnmount() {
console.log("Remove handler");
const os = document.getElementById("outside-react");
os.removeEventListener("mouseover", handleMouseOver);
}
render() {
const { n } = this.state;
return (
<div>
<strong>Info:</strong> Click button to update N in state, then hover the
orange box. Open the console to see how frequently the handler is
added/removed
<br />
<button onClick={() => this.setState({ n: n + 1 })}>+</button>
<br />
state inside react: {n}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
注意添加/删除处理程序如何只添加一次(显然忽略了 App 组件未卸载的事实),尽管状态发生了变化。
我正在寻找一种用钩子复制它的方法
【问题讨论】:
-
使用
ref而不是state。它不漂亮,但你在这里想要做的也不是。 -
谢谢托马斯。您能否详细说明上述方法的哪些地方不“漂亮”?在基于类的 React 方法中,它只是
componentDidMount和componentWillUnmount。我正在尝试复制设置和清理的行为。 -
How to register event with useEffect hooks? 包含访问
useEffect内部状态的所有不同方法的详细比较。让我知道,如果这对你有用。 -
@Chris 在这里给出了答案,以更好地适应您的阅读状态。希望,这有帮助
-
@Mordechai 第三个和第四个选项都可以用于读取状态。虽然这确实与其他答案有所不同 - 感谢您提及。
标签: javascript reactjs react-hooks