#reactjs #react-router #material-ui #navigationbar
Вопрос:
Я сталкиваюсь с этой проблемой, когда создаю нижнюю панель навигации для своего веб-сайта:
Таким образом, у него есть 3 кнопки: Главная, Профиль, Совпадения. Я хочу переключаться между ними. Однако я заметил, что, когда я нажимаю на кнопку «Профиль», страница переключается на вкладку «Профиль», но кнопка по-прежнему остается в том же начальном положении, пока я дважды не щелкну по ней. Поэтому я отладил и обнаружил эту проблему:
Очевидно, когда я нажимаю на кнопку, она все еще остается на том же пути? Вот мой код для нижней навигации:
import * as React from 'react';
import { Paper } from '@mui/material';
import BottomNavigation from '@mui/material/BottomNavigation';
import BottomNavigationAction from '@mui/material/BottomNavigationAction';
import ForumIcon from '@mui/icons-material/Forum';
import { Link } from 'react-router-dom';
import { withRouter } from 'react-router';
import HomeIcon from '@mui/icons-material/Home';
import PersonIcon from '@mui/icons-material/Person';
function BottomNav(props) {
const [value, setValue] = React.useState(1);
console.log('current path', props.location.pathname);
const handleChange = () => {
if(props.location.pathname == '/match'){
setValue(0);
}
if(props.location.pathname == '/'){
setValue(1);
}
if(props.location.pathname == '/profile'){
setValue(2);
}
console.log('value is', value, 'on path', props.location.pathname);
}
return (
<Paper sx={{ position: 'fixed', bottom: 0, left: 0, right: 0 }} elevation={3}>
<BottomNavigation
value={value}
onChange={handleChange}
showLabels
>
<BottomNavigationAction
component={Link}
to="/match"
label="Matches"
icon={<ForumIcon />} />
<BottomNavigationAction
component={Link}
to="/"
label="Home"
icon={<HomeIcon />} />
<BottomNavigationAction
component={Link}
to="/profile"
label="Profile"
icon={<PersonIcon />} />
</BottomNavigation>
</Paper>
);
}
export default withRouter(BottomNav);
Это компонент, содержащий панель навигации:
import React from "react";
import { Route, Switch } from "react-router-dom";
import Login from "../../Auth/Login";
import Logout from "../../Auth/Logout";
import Register from "../../Auth/Register";
import Dashboard from "../../Dashboard";
import Landing from "../../Landing";
import Profile from "../../Profile";
import Home from "../../Home"
import { Role } from "../Authentication";
import ProtectedRoute from "../Authentication/ProtectedRoute";
import ErrorRoute from "./ErrorRoute";
import CreateListing from '../../Listing/CreateListing';
import UpdateListing from '../../Listing/UpdateListing';
import ListingList from '../../Listing';
import ListingDisplay from '../../Listing/ListingDisplay';
import Forgot from "../../Auth/Forgot";
import AddBio from "../../Profile/AddBio";
import Match from "../../Match/Match";
import BottomNav from "../Navigation/BottomNav";
const Router = () => (
<>
<Switch>
<Route exact path="/login" component={Login} />
<Route exact path="/logout" component={Logout} />
<Route exact path="/register" component={Register} />
<Route exact path="/forgot" component={Forgot} />
<Route exact path="/landing" component={Landing} />
{/* Protected */}
<ProtectedRoute exact roles={[Role.Admin]} path="/dashboard" component={Dashboard} />
<ProtectedRoute exact roles={[Role.Flatee]} path="/addbio" component={AddBio} />
<ProtectedRoute exact roles={[Role.Flat]} path="/newlisting" component={CreateListing} />
<ProtectedRoute exact path="/" component={Home} />
<ProtectedRoute exact roles={[Role.Flat]} path="/updatelisting" component={UpdateListing} />
<ProtectedRoute exact roles={[Role.Flat]} path="/listings" component={ListingList} />
<ProtectedRoute exact path="/listing/display" component={ListingDisplay} />
<ProtectedRoute exact path="/profile" component={Profile} />
<ProtectedRoute exact path="/match" component={Match} />
<Route component={ErrorRoute} />
</Switch>
<BottomNav/>
</>
);
export default Router;
Ответ №1:
Это связано с тем, что в момент срабатывания handleChange
обратного вызова вы все еще находитесь на текущем маршруте, прежде чем react-маршрутизатор перейдет на новую страницу, поэтому location.pathname
новый маршрут не задан. И setState()
устанавливает текущую переменную индекса, чтобы ничего не менялось
const handleChange = () => {
if(props.location.pathname == '/match'){
setValue(0);
}
// when you're on home page and click the profile tab, setState(1) is called
// which is meaningless
if(props.location.pathname == '/'){
setValue(1);
}
if(props.location.pathname == '/profile'){
setValue(2);
}
console.log('value is', value, 'on path', props.location.pathname);
}
Когда react-маршрутизатор перейдет на новую страницу, BottomNav
будет повторно отображен, вы должны получить индекс, основанный на обновленном props.location.pathname
:
function getPageIndex(route) {
switch (route) {
case '/match': return 0;
case '/': return 1;
case '/profile': return 2;
default: return 0;
}
}
function BottomNav(props) {
const value = getPageIndex(props.location.pathname);
return (
<Paper sx={{ position: 'fixed', bottom: 0, left: 0, right: 0 }} elevation={3}>
<BottomNavigation value={value} showLabels>
<BottomNavigationAction
component={Link}
to="/match"
label="Matches"
icon={<ForumIcon />} />
{...}
</BottomNavigation>
</Paper>
);
}
Комментарии:
1. В таком случае, какой была бы функция {handleChange}?
2. о, черт возьми, я все уладил! Большое спасибо!