我想订阅 Solidity 事件监听器,但在渲染期间 useEffect 调用了两次。如何取消订阅活动或如何处理?
useEffect(() => {
console.log('ADD');
counterContract.events.Increment().on('data', (event) => ReadContractValue());
counterContract.events.Decrement().on('data', (event) => ReadContractValue());
return () => {
console.log('REMOVE');
counterContract.events.Decrement().unsubscribe();
counterContract.events.Increment().removeAllListeners();
};
}, []);
它写道:
ADD
REMOVE
ADD
但是两个事件监听器仍然被订阅。
您应该在调用
.on()
之前获取订阅对象,因为该对象包含卸载组件时需要调用的 unsubscribe
函数:
const isSubscribedRef = useRef(false);
useEffect(() => {
if (isSubscribedRef.current) return;
isSubscribedRef.current = true;
const incrementSubscription = counterContract.events.Increment();
const decrementSubscription = counterContract.events.Decrement();
incrementSubscription.on('data', (event) => ReadContractValue());
decrementSubscription.on('data', (event) => ReadContractValue());
return () => {
incrementSubscription.unsubscribe();
decrementSubscription.unsubscribe();
};
}, []);
请参阅 Web3.js 文档中的掌握事件订阅。
另一方面,如果您在开发模式下使用 React 18 和
useEffect()
,您 React.StrictMode
可能会运行两次,因为它会挂载您的组件两次,如 React 18 升级帖子中所述。
我添加了
ref
来防止这种情况发生,但您不应该使用/需要它,因为您的组件在重新安装后应该按预期工作。