英文:
BrowserRouter is not a <Route> component. All component children of <Routes>must be a<Route>or<React.Fragment>router component already exist in App.js
问题
在创建我的CRM系统时,遇到了React Router中与组件渲染错误有关的bug,我猜测问题可能是路由无法推送到组件内部,但无论如何,我不知道如何解决这个问题,谢谢)
import {AppBar,
Box,
CssBaseline,
Divider,
Drawer,
List,
ListItem,
ListItemButton,
ListItemIcon,
ListItemText,
Toolbar,
Typography,
ListSubheader,
Breadcrumbs,
Link, styled} from '@mui/material'
import StackedLineChartIcon from '@mui/icons-material/StackedLineChart';
import PeopleOutlineIcon from '@mui/icons-material/PeopleOutline';
import WorkOutlineIcon from '@mui/icons-material/WorkOutline';
import NavigateNextIcon from '@mui/icons-material/NavigateNext';
import HomeIcon from '@mui/icons-material/Home';
import { useState,useMemo, Fragment } from 'react';
import { BrowserRouter as Route, Routes, Router } from "react-router-dom";
import EmployeeDashboard from "../main-module/components/EmployeeDashboard";
import CollapsibleTable from '../main-module/components/ClientsList';
import EmployeeStats from '../main-module/components/EmployeeStats';
import ProfileMenu from '../main-module/components/ProfileMenu';
import EmployeeOptions from '../main-module/components/EmployeeOptions';
const drawerWidth = 240;
const StyledListItemBtn = styled(ListItemButton)(({ theme }) => ({
borderRadius: "4px"
}));
const WorkPage = () => {
const [component, setComponent] = useState("call");
const [selectedIdx, setSelectedIdx] = useState(2);
const handleItemClick = (idx) => {
setSelectedIdx(idx);
};
const drawer = (
<Box >
<Toolbar sx={{ display: "flex", alignItems: "center", justifyContent: "space-around" }}>
<Typography variant='h5'>office.kr</Typography>
</Toolbar>
<Divider />
<List
subheader={
<ListSubheader>CRM</ListSubheader>
}>
<ListItem>
<StyledListItemBtn
selected={selectedIdx === 0}
onClick={() => {setComponent("stats"); handleItemClick(0)}}
>
<ListItemIcon>
<StackedLineChartIcon color='secondary'/>
</ListItemIcon>
<ListItemText primary="Моя статистика" />
</StyledListItemBtn>
</ListItem>
<ListItem>
<StyledListItemBtn
selected={selectedIdx === 1}
onClick={() => {setComponent("clients"); handleItemClick(1)}}
>
<ListItemIcon>
<PeopleOutlineIcon color='secondary'/>
</ListItemIcon>
<ListItemText primary="Мои клиенты"/>
</StyledListItemBtn>
</ListItem>
<ListItem>
<StyledListItemBtn
selected={selectedIdx === 2}
onClick={() => {setComponent("call"); handleItemClick(2)}}
>
<ListItemIcon>
<WorkOutlineIcon color='secondary'/>
</ListItemIcon>
<ListItemText primary="Обзвон" />
</StyledListItemBtn>
</ListItem>
</List>
<Divider />
<EmployeeOptions />
</Box>
);
const setContent = () => {
switch (component) {
case 'call':
return <Route path="/dashboard" element={<EmployeeDashboard />} />;
case 'clients':
return <Route path="/clients" element={<CollapsibleTable />} />;
case 'stats':
return <Route path="/stats" element={<EmployeeStats />} />;
case 'error':
return <p>Error</p>;
default:
throw new Error('Unexpected process state');
}
}
const elements = useMemo(() => {
return setContent();
// eslint-disable-next-line
}, [component])
const breadcrumbs = [
<Link underline="hover"
key="1"
href="/"
sx={{ display: 'flex', alignItems: 'center' }}
>
<HomeIcon sx={{ mr: 1 }} fontSize="inherit" />
Главная
</Link>,
<Link
underline="hover"
key="2"
href="/"
>
CRM
</Link>,
<Typography key="3">
Обзвон
</Typography>,
];
return (
<Box sx={{ display: 'flex' }}>
<CssBaseline />
<AppBar
position="fixed"
sx={{
width: { sm: `calc(100% - ${drawerWidth}px)` },
ml: { sm: `${drawerWidth}px` },
backgroundColor: "#161b22",
borderBottom: "1px solid #30363d !important"
}}>
<Toolbar>
<Typography sx={{flexGrow: 1}} variant="h6" color="textSecondary">TestEmp</Typography>
<ProfileMenu sx={{flexGrow: 0}}/>
</Toolbar>
</AppBar>
<Box
component="nav"
sx={{ width: { sm: drawerWidth }, flexShrink: { sm: 0 } }}
>
<Drawer variant="temporary">
{drawer}
</Drawer>
<Drawer
variant="permanent"
sx={{
display: { xs: 'none', sm: 'block' },
'& .MuiDrawer-paper': { boxSizing: 'border-box', width: drawerWidth },
}}
open
>
{drawer}
</Drawer>
</Box>
<Box
component="main"
sx={{ flexGrow: 1, p: 2.5, width: { sm: `calc(100% - ${drawerWidth}px)` } }}
>
<Toolbar/>
<Breadcrumbs
separator={<NavigateNextIcon fontSize="small" />}
sx={{ pb: 1.5, pl: 0.5 }}
>
{breadcrumbs}
</Breadcrumbs>
<Routes>
{elements}
</Routes>
</Box>
</Box>
);
}
export default WorkPage;
英文:
Creating my own CRM system, encountered a bug in React Router which is related to component rendering error, I guess the problem is that routes cannot be pushed inside components, anyway I don't know how to solve this problem, thanks)
import {AppBar,
Box,
CssBaseline,
Divider,
Drawer,
List,
ListItem,
ListItemButton,
ListItemIcon,
ListItemText,
Toolbar,
Typography,
ListSubheader,
Breadcrumbs,
Link, styled} from '@mui/material'
import StackedLineChartIcon from '@mui/icons-material/StackedLineChart';
import PeopleOutlineIcon from '@mui/icons-material/PeopleOutline';
import WorkOutlineIcon from '@mui/icons-material/WorkOutline';
import NavigateNextIcon from '@mui/icons-material/NavigateNext';
import HomeIcon from '@mui/icons-material/Home';
import { useState,useMemo, Fragment } from 'react';
import { BrowserRouter as Route, Routes, Router } from "react-router-dom";
import EmployeeDashboard from "../main-module/components/EmployeeDashboard";
import CollapsibleTable from '../main-module/components/ClientsList';
import EmployeeStats from '../main-module/components/EmployeeStats';
import ProfileMenu from '../main-module/components/ProfileMenu';
import EmployeeOptions from '../main-module/components/EmployeeOptions';
const drawerWidth = 240;
const StyledListItemBtn = styled(ListItemButton)(({ theme }) => ({
borderRadius: "4px"
}));
const WorkPage = () => {
const [component, setComponent] = useState("call");
const [selectedIdx, setSelectedIdx] = useState(2);
const handleItemClick = (idx) => {
setSelectedIdx(idx);
};
const drawer = (
<Box >
<Toolbar sx={{ display: "flex", alignItems: "center", justifyContent: "space-around" }}>
<Typography variant='h5'>office.kr</Typography>
</Toolbar>
<Divider />
<List
subheader={
<ListSubheader>CRM</ListSubheader>
}>
<ListItem>
<StyledListItemBtn
selected={selectedIdx === 0}
onClick={() => {setComponent("stats"); handleItemClick(0)}}
>
<ListItemIcon>
<StackedLineChartIcon color='secondary'/>
</ListItemIcon>
<ListItemText primary="Моя статистика" />
</StyledListItemBtn>
</ListItem>
<ListItem>
<StyledListItemBtn
selected={selectedIdx === 1}
onClick={() => {setComponent("clients"); handleItemClick(1)}}
>
<ListItemIcon>
<PeopleOutlineIcon color='secondary'/>
</ListItemIcon>
<ListItemText primary="Мои клиенты"/>
</StyledListItemBtn>
</ListItem>
<ListItem>
<StyledListItemBtn
selected={selectedIdx === 2}
onClick={() => {setComponent("call"); handleItemClick(2)}}
>
<ListItemIcon>
<WorkOutlineIcon color='secondary'/>
</ListItemIcon>
<ListItemText primary="Обзвон" />
</StyledListItemBtn>
</ListItem>
</List>
<Divider />
<EmployeeOptions />
</Box>
);
const setContent = () => {
switch (component) {
case 'call':
return <Route path="/dashboard" element={<EmployeeDashboard />} />;
case 'clients':
return <Route path="/clients" element={<CollapsibleTable />} />;
case 'stats':
return <Route path="/stats" element={<EmployeeStats />} />;
case 'error':
return <p>Error</p>;
default:
throw new Error('Unexpected process state');
}
}
const elements = useMemo(() => {
return setContent();
// eslint-disable-next-line
}, [component])
const breadcrumbs = [
<Link underline="hover"
key="1"
href="/"
sx={{ display: 'flex', alignItems: 'center' }}
>
<HomeIcon sx={{ mr: 1 }} fontSize="inherit" />
Главная
</Link>,
<Link
underline="hover"
key="2"
href="/"
>
CRM
</Link>,
<Typography key="3">
Обзвон
</Typography>,
];
return (
<Box sx={{ display: 'flex' }}>
<CssBaseline />
<AppBar
position="fixed"
sx={{
width: { sm: `calc(100% - ${drawerWidth}px)` },
ml: { sm: `${drawerWidth}px` },
backgroundColor: "#161b22",
borderBottom: "1px solid #30363d !important"
}}>
<Toolbar>
<Typography sx={{flexGrow: 1}} variant="h6" color="textSecondary">TestEmp</Typography>
<ProfileMenu sx={{flexGrow: 0}}/>
</Toolbar>
</AppBar>
<Box
component="nav"
sx={{ width: { sm: drawerWidth }, flexShrink: { sm: 0 } }}
>
<Drawer variant="temporary">
{drawer}
</Drawer>
<Drawer
variant="permanent"
sx={{
display: { xs: 'none', sm: 'block' },
'& .MuiDrawer-paper': { boxSizing: 'border-box', width: drawerWidth },
}}
open
>
{drawer}
</Drawer>
</Box>
<Box
component="main"
sx={{ flexGrow: 1, p: 2.5, width: { sm: `calc(100% - ${drawerWidth}px)` } }}
>
<Toolbar/>
<Breadcrumbs
separator={<NavigateNextIcon fontSize="small" />}
sx={{ pb: 1.5, pl: 0.5 }}
>
{breadcrumbs}
</Breadcrumbs>
<Routes>
{elements}
</Routes>
</Box>
</Box>
);
}
export default WorkPage;
答案1
得分: 0
问题在于您将BrowserRouter
用作Route
,这是不正确的。BrowserRouter
应该用作Routes
的包装,而Routes
则是Route
的包装。
通常,您会像这样导入三个模块:
import { BrowserRouter, Route, Routes } from "react-router-dom";
然后在您的应用程序中的某个地方定义它们:
<BrowserRouter>
<Routes>
<Route path="/" element={<div>Hello World</div>} />
</Routes>
</BrowserRouter>
不要这样做:
import { BrowserRouter as Route, ... }
英文:
The issue is you're using BrowserRouter as a Route which is incorrect. That's meant to be a wrapper for Routes which is a wrapper for Route.
Typically you would bring in 3 imports like this:
import { BrowserRouter, Route, Routes } from "react-router-dom";
Then inside your app somewhere define them:
<BrowserRouter>
<Routes>
<Route path="/" element={<div>Hello World</div>} />
</Routes>
</BrowserRouter>
Don't do this:
import { BrowserRouter as Route, ... }
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论