React中使用Material UI Link跳转至其他组件的实现方法
问题根因
你的代码存在两个核心错误,直接导致路由跳转无法生效:
- 错误放置了
BrowserRouter:react-router-dom要求应用内所有路由相关组件必须包裹在同一个BrowserRouter实例下,你单独给注册页路由包了一层独立的BrowserRouter,和登录页不在同一个路由上下文里,跳转时根本匹配不到对应的路由规则。 - 注册入口的MUI Link未对接路由:你当前写的注册跳转Link的
href指向外部地址,既没有绑定react-router-dom的客户端路由跳转能力,也没有指向你定义的/register路径。
修复步骤
- 把根级
BrowserRouter提到应用最外层(通常是App.jsx文件),包裹所有页面组件,不要在单个业务组件里单独嵌套BrowserRouter。 - 删除你当前写的内嵌式
Register路由组件,把登录、注册的路由规则统一放在根路由表中配置。 - 注册入口的MUI Link通过
component属性绑定为RouterLink,添加to属性指向/register路径,替换掉原来的外部href配置。
修正后的代码示例
首先是根组件App.jsx的路由配置,这里统一放置全局Router和路由表:
// App.jsx import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'; import LoginCard from './LoginCard'; import RegisterPage from './Register'; function App() { return ( <BrowserRouter> <Routes> {/* 登录页路由 */} <Route path="/login" element={<LoginCard />} /> {/* 注册页路由 */} <Route path="/register" element={<RegisterPage />} /> {/* 未匹配路径默认重定向到登录页 */} <Route path="*" element={<Navigate to="/login" replace />} /> </Routes> </BrowserRouter> ) } export default App;
然后是修正后的LoginCard组件代码,删除多余的内嵌路由配置,修正跳转Link的写法:
import React, { useState } from 'react'; import Avatar from '@mui/material/Avatar'; import Button from '@mui/material/Button'; import CssBaseline from '@mui/material/CssBaseline'; import TextField from '@mui/material/TextField'; import FormControlLabel from '@mui/material/FormControlLabel'; import Checkbox from '@mui/material/Checkbox'; import Grid from '@mui/material/Grid'; import Box from '@mui/material/Box'; import Typography from '@mui/material/Typography'; import Container from '@mui/material/Container'; import { createTheme, ThemeProvider } from '@mui/material/styles'; import Link from '@mui/material/Link'; // 引入react-router的Link组件,重命名避免和MUI Link命名冲突 import { Link as RouterLink } from "react-router-dom"; function LoginCard({ Login, error }) { const [details, setDetails] = useState({ username: "", password: "" }) const onFormSubmit = (e) => { e.preventDefault(); Login(details); } const theme = createTheme(); function Copyright(props) { return ( <Typography variant="body2" color="text.secondary" align="center" {...props}> {'Copyright © '} <Link color="inherit" href="/"> Fiin Frisører </Link>{' '} {new Date().getFullYear()} {'.'} </Typography> ); } return( <ThemeProvider theme={theme}> <Container component="main" maxWidth="xs"> <CssBaseline /> <Box sx={{ marginTop: 8, display: 'flex', flexDirection: 'column', alignItems: 'center', }} > <Avatar sx={{ m: 1, bgcolor: 'secondary.main' }}> </Avatar> <Typography component="h1" variant="h5"> Sign in </Typography> <Box component="form" onSubmit={onFormSubmit} noValidate sx={{ mt: 1 }}> <TextField margin="normal" required fullWidth id="username" label="Username" name="username" onChange={e=> setDetails({...details, username: e.target.value})} /> <TextField margin="normal" required fullWidth name="password" label="Password" type="password" id="password" onChange={e=> setDetails({...details, password: e.target.value})} /> <FormControlLabel control={<Checkbox value="remember" color="primary" />} label="Remember me" /> <Button type="submit" fullWidth variant="contained" sx={{ mt: 3, mb: 2 }} > Sign In </Button> <Grid container> <Grid item xs> <Link href="#" variant="body2"> Forgot password? </Link> </Grid> <Grid item> {/* 绑定路由组件,指定跳转路径 */} <Link component={RouterLink} to="/register" variant="body2" > Don't have an account yet? </Link> </Grid> </Grid> </Box> </Box> <Copyright sx={{ mt: 8, mb: 4 }} /> </Container> </ThemeProvider> ); }; export default LoginCard;
注意事项
- 整个应用只需要在最顶层放置一次
BrowserRouter即可,多个独立的Router实例会造成路由上下文隔离,导致跳转、参数获取等路由相关功能全部失效。 - MUI的
Link本质是样式组件,要实现SPA无刷新路由跳转,必须通过component属性将底层渲染元素替换为react-router-dom的RouterLink,再通过to属性指定路由路径,直接写href会触发浏览器整页刷新,不符合单页应用的路由预期。
内容的提问来源于stack exchange,提问作者Alexander Brandhaug
相关产品推荐
相关产品推荐

