React и antd: Router не перерисовывает компоненты
У меня есть простая веб-страница со страницами входа и поиска. У меня также есть панель навигации вверху, позволяющая переключаться между ними. Базовый App.jsвыглядит следующим образом:
const history = createBrowserHistory();
function App() {
return (
<Router history={history}>
<CustomLayout>
<Switch>
<BaseRouter/>
</Switch>
</CustomLayout>
</Router>
);
}
export default App;
Теперь BaseRouterи CustomLayoutпросто
const BaseRouter = () => (
<div>
<Route exact path={"/list"} component={ItemsList}/>
<Route path={"/login"} component={LoginForm}/>
</div>
);
export default BaseRouter;
и
const CustomLayout = ({children}) => {
return(
<>
<Navbar/>
{children}
</>
);
}
export default CustomLayout;
Теперь панель навигации выглядит так
import React from "react";
import {Menu} from 'antd';
import {Link} from "react-router-dom";
const Navbar = () => {
return (
<div>
<Menu mode="horizontal" theme={"dark"}>
<Menu.Item key="list">
<Link to={"/list"}>List</Link>
</Menu.Item>
<Menu.Item key={"login"}>
<Link to={"/login"}>Sign in</Link>
</Menu.Item>
</Menu>
</div>
);
}
export default Navbar
Давайте сохраним компоненты простыми:
const Login = () => {
return (
<div>
login
</div>
);
}
export default Login
const List = () => {
return (
<div>
list
</div>
);
}
export default List
Теперь проблема в том, что когда я нажимаю ссылки на панели навигации, React не повторно отображает компоненты, даже если маршрут меняется. Я видел сотни ответов на SO, но до сих пор не могу понять.
ПРИМЕЧАНИЕ.
Для меня важно избегать обновления или перезагрузки страницы.
ИЗМЕНИТЬ
Как ни странно, когда я перехожу Routerна BrowserRotuerнего, он работает нормально, но тогда я не могу использовать свою собственную историю.
Ответы
почему бы вам не использовать BrowserRouterиз react-router-domпакета.
App.js: - использоватьBrowserRouterизreact-router-dom
import { BrowserRouter as Router, Switch } from 'react-router-dom'
function App() {
return (
<Router>
<CustomLayout>
<Switch>
<BaseRouter/>
</Switch>
</CustomLayout>
</Router>
);
}
export default App;
BaseRouter.js: - импортRouteизreact-router-dom
import { Route } from 'react-router-dom'
const BaseRouter = () => (
<div>
<Route exact path="/list" component={ItemsList}/>
<Route path="/login" component={LoginForm}/>
</div>
);
export default BaseRouter;
Navbar.js: -
import React from "react";
import {Menu} from 'antd';
import {Link} from "react-router-dom";
const Navbar = () => {
return (
<div>
<Menu mode="horizontal" theme={"dark"}>
<Menu.Item key={"list"}>
<Link to="/list">List</Link>
</Menu.Item>
<Menu.Item key={"login"}>
<Link to="/login">Sign in</Link>
</Menu.Item>
</Menu>
</div>
);
}
export default Navbar
тогда, если вы хотите использовать history: -
import { useHistory } from 'react-router-dom'
const testFunctionComponent = () => {
const history = useHistory()
const handleClick = (urlPath) => {
// you can do
history.push(urlPath) // to go anywhere
}
return (
<>
<button onClick={() => handleClick('/anypath')}>Click Me!<button>
</>
)
}
Измените свое BaseRouterс этого:
const BaseRouter = () => (
<div>
<Route exact path={"/list"} component={ItemsList}/>
<Route path={"/login"} component={LoginForm}/>
</div>
);
export default BaseRouter;
К этому :
const BaseRouter = () => (
<div>
<Route exact path="/list" component={ItemsList}/>
<Route path="/login" component={LoginForm}/>
</div>
);
export default BaseRouter;
Я считаю, что у вас не может быть div внутри переключателя. Вы не открываете компоненты Route своему оператору switch.
Следовательно, ваш URL-адрес изменяется, потому что ваша панель навигации изменяет его, но ваш переключатель не знает, что делать.
Попробуйте сменить базовый маршрутизатор на этот:
const history = createBrowserHistory();
function App() {
return (
<Router history={history}>
<CustomLayout>
<BaseRouter/>
</CustomLayout>
</Router>
);
}
export default App;
const BaseRouter = () => (
<Switch>
<Route exact path={"/list"} component={ItemsList}/>
<Route path={"/login"} component={LoginForm}/>
</Switch>
);
export default BaseRouter;
Routerнаходится на низком уровне и ожидает, что вы будете управлять вещами. BrowserRouterуже синхронизируется с историей HTML5. Если вы хотите Router, я думаю, вам нужно управлять синхронизацией самостоятельно (например, <Link onClick={() => history.push(href)}>)или прослушивать историю для обнаружения изменений. См. Обнаружение изменения маршрута с помощью response-router