React Router路由到指定页面时函数被多次调用问题求解(Web3 DApp场景)
问题原因
你遇到的checkChainID多次调用问题是React组件副作用处理不当导致的,核心问题有3个:
- 你直接把
window.ethereum事件绑定、checkChainID()调用写在了MintPage组件的顶层,组件每渲染一次这些代码就会执行一遍:不仅会反复新增重复的事件监听器,还会每次都触发checkChainID执行。 checkChainID会触发loadBlockchainData,后者内部调用了setCurrentAccount、setCurrentBalance两个状态更新方法,每次状态更新都会触发组件重新渲染,渲染又执行顶层的checkChainID,形成无限循环,调用次数自然会异常升高。- 你在入口处启用了
React.StrictMode,开发环境下它会故意让组件重复渲染两次来排查不合理的副作用,也会让你观测到的调用次数翻倍。
修复方案
使用React的useEffect钩子处理所有副作用逻辑,确保事件绑定、初始校验只在组件第一次挂载时执行一次,同时组件卸载时移除监听器,避免残留的监听触发逻辑。
关键修改代码(MintPage.js)
首先新增导入useEffect:
import React, { useState, useEffect } from 'react';
然后删除MintPage组件顶层原来的3行逻辑:
// 删掉下面这三行 window.ethereum.on('chainChanged', (_chainId) => checkChainID()); window.ethereum.on('accountsChanged', (_accounts) => loadBlockchainData()); checkChainID();
替换成下面的useEffect代码:
useEffect(() => { // 声明事件回调函数 const handleChainChange = (_chainId) => checkChainID(); const handleAccountChange = (_accounts) => loadBlockchainData(); // 绑定钱包事件监听 window.ethereum.on('chainChanged', handleChainChange); window.ethereum.on('accountsChanged', handleAccountChange); // 组件挂载时仅执行一次初始链ID校验 checkChainID(); // 清理函数:组件卸载时移除事件监听,防止内存泄漏和残留触发 return () => { window.ethereum.removeListener('chainChanged', handleChainChange); window.ethereum.removeListener('accountsChanged', handleAccountChange); } }, []); // 空依赖数组保证逻辑仅在组件挂载、卸载时执行
附加优化建议
你入口index.js里的window.ethereum.enable()是已经废弃的API,建议替换为符合当前钱包规范的写法:
// 替换原来的 window.ethereum.enable() window.ethereum.request({method: 'eth_requestAccounts'})
另外你观测到主动导航到同一路由时函数被调用2次的情况,是开发环境下React.StrictMode的默认行为,生产环境构建后会自动变成只调用1次,不需要额外处理。
内容的提问来源于stack exchange,提问作者Molly Hatchet
相关产品推荐
相关产品推荐

