组合web3UIkit+React/Moralis时出现MaxListeners Exceeded问题求助
问题:多次切换页面后触发MaxListeners Exceeded报错
我在项目中反复遇到MaxListeners Exceeded问题,多次点击导航栏切换页面后,控制台就会弹出该报错。代码无特殊逻辑,但始终找不到根因。
为排查问题,我制作了一个仅保留必要依赖的极简项目,怀疑是web3UIkit、React、Moralis和/或Next之间存在兼容问题,但无法确认。现请求帮忙找出问题原因,或提供彻底解决的方案。
相关代码文件
_app.js
import { MoralisProvider } from "react-moralis"; import "../styles/globals.css"; function MyApp({ Component, pageProps }) { return ( <MoralisProvider initializeOnMount={false}> <Component {...pageProps} /> </MoralisProvider> ); } export default MyApp;
Index.js
import Head from "next/head"; import Header from "../components/Header"; import Navbar from "../components/Navbar"; import styles from "../styles/Home.module.css"; export default function Home() { return ( <div className={styles.container}> <Head> <title>Create Next App</title> <meta name="description" content="Generated by create next app" /> <link rel="icon" href="/favicon.ico" /> </Head> <Header></Header> <Navbar></Navbar> <div>This page is an example to illustrate the maxlisteners issue</div> </div> ); }
Page1.js
import Head from "next/head"; import Header from "../components/Header"; import Navbar from "../components/Navbar"; import styles from "../styles/Home.module.css"; export default function Home() { return ( <div className={styles.container}> <Head> <title>Create Next App</title> <meta name="description" content="Generated by create next app" /> <link rel="icon" href="/favicon.ico" /> </Head> <Header></Header> <Navbar></Navbar> <div> Page 1: This page is an example to illustrate the maxlisteners issue </div> </div> ); }
Header.js(组件)
import { ConnectButton } from "@web3uikit/web3"; export default function Header() { return ( <div className="p-5 border-b-2 flex flex-row bg-slate-400"> <h1 className="py-4 px-4 font-blog text-3xl">Maxlisteners Example</h1> <div className="ml-auto py-2 px-4"> <ConnectButton moralisAuth={false}></ConnectButton> </div> </div> ); }
Navbar.js(组件)
import Link from "next/link"; export default function Navbar() { return ( <div className="bg-slate-400"> <ul className="grid grid-cols-3 place-items-center py-2 border-b-2 f"> <li> <Link href="/"> <a>Home</a> </Link> </li> <li> <Link href="/page1"> <a>Page1</a> </Link> </li> </ul> </div> ); }
package.json
{ "name": "maxlisteners", "version": "0.1.0", "private": true, "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint" }, "dependencies": { "@web3uikit/core": "^0.1.5", "@web3uikit/icons": "^0.1.5", "@web3uikit/web3": "^0.1.5", "magic-sdk": "^9.0.0", "moralis": "^2.0.3", "next": "12.2.5", "react": "18.2.0", "react-dom": "18.2.0", "react-moralis": "^1.4.1" }, "devDependencies": { "eslint": "8.22.0", "eslint-config-next": "12.2.5" } }
问题原因与解决方案
根因分析
核心问题是**@web3uikit/web3的ConnectButton组件在页面切换时未正确清除事件监听器**:每次页面挂载都会新增监听器,而页面卸载时这些监听器未被清理,累积超过Node.js默认的最大监听器数量(默认10个)后触发报错。
解决方法
1. 升级依赖版本(推荐)
@web3uikit早期版本(如你使用的0.1.5)存在内存泄漏问题,升级到最新稳定版可修复。执行命令:
npm update @web3uikit/core @web3uikit/icons @web3uikit/web3
2. 全局提升ConnectButton
将Header组件(包含ConnectButton)放到_app.js中作为全局组件,避免每次页面切换重复挂载:
修改_app.js:
import { MoralisProvider } from "react-moralis"; import "../styles/globals.css"; import Header from "../components/Header"; function MyApp({ Component, pageProps }) { return ( <MoralisProvider initializeOnMount={false}> <Header /> <Component {...pageProps} /> </MoralisProvider> ); } export default MyApp;
同时移除Index.js和Page1.js中的<Header></Header>引用,让Header仅挂载一次。
3. 手动清理监听器(临时方案)
若暂时无法升级依赖,可在Header组件中通过useEffect手动清理事件监听器:
修改Header.js:
import { ConnectButton } from "@web3uikit/web3"; import { useEffect } from "react"; export default function Header() { useEffect(() => { return () => { const emitter = window.ethereum?.provider; if (emitter?.removeAllListeners) { emitter.removeAllListeners("accountsChanged"); emitter.removeAllListeners("chainChanged"); } }; }, []); return ( <div className="p-5 border-b-2 flex flex-row bg-slate-400"> <h1 className="py-4 px-4 font-blog text-3xl">Maxlisteners Example</h1> <div className="ml-auto py-2 px-4"> <ConnectButton moralisAuth={false}></ConnectButton> </div> </div> ); }
内容的提问来源于stack exchange,提问作者Patrick H
相关产品推荐
相关产品推荐

