次のような React コンポーネントがあります:
import React, { PropTypes, Component } from 'react'
class MyComponent extends Component {
componentDidMount() {
window.addEventListener("beforeunload", function (event) {
console.log("hellooww")
event.returnValue = "Hellooww"
})
}
componentWillUnmount() {
window.removeEventListener("beforeunload", function (event) {
console.log("hellooww")
event.returnValue = "Hellooww"
})
}
render() {
return (
<div>
Some content
</div>
)
}
}
export default MyComponent
ここで、イベント リストがコンポーネントに追加されます。ページを更新すると、ページを離れるように求めるポップアップが表示されます。
しかし、別のページに移動して再度更新すると、同じポップアップが表示されます。
eventListener
のコンポーネントから を削除していますcomponentWillUnmount
。 それなのに、なぜ削除されないのでしょうか?
beforeunload
他のページのイベントを削除するにはどうすればよいですか?
ベストアンサー1
はremoveEventListener
、 で割り当てられた同じコールバックへの参照を取得する必要がありますaddEventListener
。関数を再作成してもうまくいきません。解決策は、コールバックを別の場所 (この例では) に作成しonUnload
、それをaddEventListener
と の両方への参照として渡すことですremoveEventListener
。
import React, { PropTypes, Component } from 'react';
class MyComponent extends Component {
onUnload = e => { // the method that will be used for both add and remove event
e.preventDefault();
e.returnValue = '';
}
componentDidMount() {
window.addEventListener("beforeunload", this.onUnload);
}
componentWillUnmount() {
window.removeEventListener("beforeunload", this.onUnload);
}
render() {
return (
<div>
Some content
</div>
);
}
}
export default MyComponent
Reactフック
、およびフックをbeforeunload
使用して、イベント処理をカスタム フックに抽象化できます。useRef
useEffect
カスタムフックはuseUnload
関数(fn
)を受け取り、それを現在の参照に割り当てます。これはuseEffect
(コンポーネントのマウント時に)1回呼び出され、イベントハンドラをcb.current
(定義された) を呼び出し、コンポーネントが削除されたときにイベント ハンドラーを削除するクリーンアップ関数を返します。
import { useRef, useEffect } from 'react';
const useUnload = fn => {
const cb = useRef(fn); // init with fn, so that type checkers won't assume that current might be undefined
useEffect(() => {
cb.current = fn;
}, [fn]);
useEffect(() => {
const onUnload = (...args) => cb.current?.(...args);
window.addEventListener("beforeunload", onUnload);
return () => window.removeEventListener("beforeunload", onUnload);
}, []);
};
export default useUnload;
使用法:
const MyComponent = () => {
useUnload(e => {
e.preventDefault();
e.returnValue = '';
});
return (
<div>
Some content
</div>
);
};