React钱包断开后自动重定向首页失败问题求助
问题解决思路
核心问题分析
- useNavigate报错原因:你把
<Router>嵌套在了Navbar内部,导致useNavigate钩子无法获取到正确的Router上下文。Router必须包裹整个应用的根组件,才能让所有子组件共享路由上下文。 - 自动跳转逻辑缺失:之前的代码只在渲染时判断
walletConnected状态返回跳转组件,但断开钱包的事件触发后,没有直接执行跳转操作,而是依赖组件重新渲染,这会导致跳转不及时或者失效。
具体修改步骤
1. 调整Router层级
把<Router>从NavbarMenu组件中移出,放到应用的最顶层(比如App.js),确保所有路由相关组件都在Router上下文内:
// App.js示例 import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; import Home from './Home'; import MyAccount from './MyAccount'; function App() { return ( <Router> <Routes> <Route path="/" element={<Home />} /> <Route path="/myaccount" element={<MyAccount />} /> </Routes> </Router> ); }
2. 修复NavbarMenu组件的跳转逻辑
- 移除组件内部的
<Router>标签 - 在
accountsChanged事件触发时直接调用navigate跳转 - 替换废弃的
Redirect为Navigate组件(react-router-dom v6语法) - 添加事件监听清理,防止内存泄漏
修改后的NavbarMenu代码:
import { Nav, Navbar, Container, Button } from 'react-bootstrap'; import { useNavigate, Navigate } from 'react-router-dom'; import { useState, useEffect } from 'react'; const NavbarMenu = ({ typeNavbar }) => { const [walletConnected, setWalletConnected] = useState(false); const navigate = useNavigate(); useEffect(() => { const handleAccountsChanged = async (accounts) => { if (!accounts.length) { setWalletConnected(false); // 断开钱包后直接跳转首页 navigate("/"); } else { setWalletConnected(true); } }; // 监听钱包账户变化 window.ethereum?.on("accountsChanged", handleAccountsChanged); // 组件卸载时移除监听 return () => { window.ethereum?.removeListener("accountsChanged", handleAccountsChanged); }; }, [navigate]) const setFinalNavbar = () => { if (typeNavbar === "homepage") { return walletConnected ? <Nav.Link href="/myaccount">My Account</Nav.Link> : <Button className={navbar_styles.connect_btn} variant="outline-success" onClick={connectWallet}>Connect Wallet</Button>; } else { return walletConnected ? <Nav.Link href="/" className='text-success'>Back to home</Nav.Link> : <Navigate to="/" replace />; } } return ( <Navbar sticky="top" bg="dark" variant="dark" expand="lg"> <Container> <Navbar.Brand href="#home"> <img src="/favicon.ico" width="30" height="30" className="d-inline-block align-top" alt="React Bootstrap logo" />{' '} Four-Leaf </Navbar.Brand> <Navbar.Toggle aria-controls="basic-navbar-nav" /> <Navbar.Collapse id="basic-navbar-nav"> <Nav className="me-auto"> {typeNavbar === "personal" ? <> <Nav.Link href="#home">Purchased numbers</Nav.Link> <Nav.Link href="#bet-number">Previous numbers</Nav.Link> </> : <> <Nav.Link href="#home">Home</Nav.Link> <Nav.Link href="#bet-number">Bet</Nav.Link> <Nav.Link href="#last-raffles">Last raffles</Nav.Link> <Nav.Link href="#link">Instructions</Nav.Link> </> } {setFinalNavbar()} </Nav> </Navbar.Collapse> </Container> </Navbar> ) } export default NavbarMenu;
3. 注意事项
- 确保你的
react-router-dom版本是v6,v5和v6的路由语法差异很大,Redirect在v6中已被Navigate替代 - 调用
window.ethereum时加上可选链?.,防止用户未安装钱包时报错 - 事件监听一定要在组件卸载时移除,避免内存泄漏
内容的提问来源于stack exchange,提问作者asusrid
相关产品推荐
相关产品推荐

