英文:
Nav Link not rerendering page when clicked. Force update freezes page
问题
我正在构建的网站上有一个导航栏。导航栏中的链接指向页面中的一个部分(#id),但不会跳转到该部分,只会更新网址。如果我在地址栏中键入网址,它能正常工作,但当使用链接时却没有任何反应。
只有在我强制页面重新渲染时才起作用,但在重新渲染后,页面会冻结,并且控制台会报错:Uncaught TypeError: Cannot read properties of undefined (reading 'forceUpdate')
。我尝试过在onClick
事件中使用setState
来强制重新渲染,也尝试过使用withRouter
在NavBar
组件上。
我阅读过如果必须强制页面渲染,那么可能我做错了什么,但我刚开始学习React,过去几天一直在寻找更好的解决方法,但仍然找不到更好的方法。
英文:
I have a nav bar for a website I'm building. The links in the nav bar to a section (#id) in the page but do not go to the section and only update the url. If I type in the url in the address bar, it works correctly but when using the link nothing happens.
It only works if I force the page to rerender, but after rerendering the page freezes and I get an error in the console: Uncaught TypeError: Cannot read properties of undefined (reading 'forceUpdate')
. I added an onClick
and also tried using setState
to force re-render.
Index.js
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
);
App.js
function App() {
return (
<div>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/home" element={<Home />} />
</Routes>
</div>
);
}
export default App;
Home.jsx
function Home() {
return (
<div>
<Container fluid>
<NavBar />
<HomeContent />
</Container>
<Pricing />
<Footer />
</div>
);
}
export default Home;
NavBar.jsx
function handleClick() {
this.setState({ state: this.state });
// this.forceUpdate();
}
function NavBar() {
return (
<>
<Navbar variant="dark" expand="lg">
<Container>
<Navbar.Brand onClick={handleClick} as={Link} to="/home">
</Navbar.Brand>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="justify-content-end flex-grow-1 pe-3">
<Nav.Link onClick={handleClick} as={Link} to="/home">
Home
</Nav.Link>
<Nav.Link onClick={handleClick} as={Link} to="/home#pricing">
Pricing
</Nav.Link>
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
</>
);
}
export default NavBar;
Pricing.jsx
function Pricing() {
return (
<section id="pricing">
<h2 className="section-heading">This is the pricing section</h2>
</section>
);
}
export default Pricing;
I also tried using withRouter
on the NavBar
component
I read that if I have to resort to forcing the page to render then I may be doing something wrong but I'm new to React and I've been searching for the past couple of days on better ways to do this but still couldn't find a better way to do it.
答案1
得分: 2
this.setState
和 this.forceUpdate
是较旧的 React 基于类的组件方法。它们在 React 函数组件中不起作用。
react-router-dom
单独不处理哈希链接,即导航到特定路由路径 然后 滚动到特定哈希锚点。目前 react-router-hash-link
仍然与 react-router-dom@6
配合使用。从 react-router-hash-link
中导入 HashLink
并用它替代 RRD 中的 Link
组件。
示例:
import React from "react";
import { Nav, Navbar } from "react-bootstrap";
import { Link } from "react-router-dom";
import { HashLink } from "react-router-hash-link"; // <-- 导入哈希链接
function NavBar() {
return (
<Navbar bg="dark" variant="dark" expand="lg">
<Navbar.Brand as={Link} to="/home"></Navbar.Brand>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="justify-content-end flex-grow-1 pe-3">
<Nav.Link as={Link} to="/home">
Home
</Nav.Link>
<Nav.Link as={HashLink} to="/home#pricing"> // <-- 哈希链接
Pricing
</Nav.Link>
<Nav.Link as={HashLink} to="/home#about"> // <-- 哈希链接
About
</Nav.Link>
<Nav.Link as={HashLink} to="/home#contact"> // <-- 哈希链接
Contact
</Nav.Link>
</Nav>
</Navbar.Collapse>
</Navbar>
);
}
export default NavBar;
英文:
this.setState
and this.forceUpdate
are older React class-based-only component methods. They won't work in React function components.
react-router-dom
alone doesn't deal/handle with hash links, i.e. navigating to a specific route path and then scrolling to a specific hash anchor. Currently the react-router-hash-link
still works with react-router-dom@6
. Import the HashLink
from react-router-hash-link
and use instead of the Link
component from RRD.
Example:
import React from "react";
import { Nav, Navbar } from "react-bootstrap";
import { Link } from "react-router-dom";
import { HashLink } from "react-router-hash-link"; // <-- import hash link
function NavBar() {
return (
<Navbar bg="dark" variant="dark" expand="lg">
<Navbar.Brand as={Link} to="/home"></Navbar.Brand>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="justify-content-end flex-grow-1 pe-3">
<Nav.Link as={Link} to="/home">
Home
</Nav.Link>
<Nav.Link as={HashLink} to="/home#pricing"> // <-- hash link
Pricing
</Nav.Link>
<Nav.Link as={HashLink} to="/home#about"> // <-- hash link
About
</Nav.Link>
<Nav.Link as={HashLink} to="/home#contact"> // <-- hash link
Contact
</Nav.Link>
</Nav>
</Navbar.Collapse>
</Navbar>
);
}
export default NavBar;
答案2
得分: -1
解决问题的最佳方法是在您的 Web 应用程序中创建 React 路由器结构。我建议您阅读 React 路由器的入门页面。
此外,在您的情况下,我建议您创建以下结构的 React 路由器结构:
您将有一个主 index.js
文件:
const router = createBrowserRouter([
{
path: "/",
element: <Layout />,
children: [
{
path: "mainpage/",
element: <MainPage />,
},
],
},
]);
您将没有 app.js
文件。您只会有一个 layout.jsx
文件:
import { Outlet } from 'react-router-dom';
import Nav from "./components/Nav";
const Layout = () => {
return (<>
<Nav />
<Outlet />
</>)
}
您只需在 index.js
中添加路径和更多子项。只需创建一些组件并将它们添加到 children 数组中作为主页面。
在您的导航组件中,您必须像以下导航组件示例中那样有链接到您的页面:
import React from 'react';
import { Link } from "react-router-dom";
function Nav(props) {
return (
<header className="header">
<div className="header-container">
<nav className="header-nav">
<ul className="nav-list">
<li>
<Link to={`mainpage/`}>Home</Link>
</li>
<li>
<Link to={`News/`}>News</Link>
</li>
<li>
<Link to={`About/`}>About</Link>
</li>
<li>
<Link to={`Contacts`}>Contacts</Link>
</li>
</ul>
</nav>
</div>
</header>
);
}
export default Nav;
希望这能解决您的问题。
英文:
The best way to solve your problem to create React router structure in your web app. I suggest you to go through React router beginners page.
Also, in your case I suggest to create React router structure such as this structure:
You will have the main index.js file:
const router = createBrowserRouter([
{
path: "/",
element: <Layout />,
children: [
{
path: "mainpage/",
element: <MainPage />,
},
],
},
]);
You will not have app.js file. You will just have a layout.jsx file:
import { Outlet } from 'react-router-dom';
import Nav from "./components/Nav";
const Layout = () => {
return (<>
<Nav />
<Outlet />
</>)
}
And you should just add paths and more children to index js. Just create some components and add them to children array as a main page one.
And in your nav component you must have links to your pages like in the following nav component example:
import React from 'react';
import { Link } from "react-router-dom";
function Nav(props) {
return (
<header className="header">
<div className="header-container">
<nav className="header-nav">
<ul className="nav-list">
<li>
<Link to={`mainpage/`}>Home</Link>
</li>
<li>
<Link to={`News/`}>News</Link>
</li>
<li>
<Link to={`About/`}>About</Link>
</li>
<li>
<Link to={`Contacts`}>Contacts</Link>
</li>
</ul>
</nav>
</div>
</header>
);
}
export default Nav;
I hope you will solve your issue.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论