ReactJS Bootstrap Navbar and Routing not working together - javascript

I am trying to create a simple Webapp using ReactJS, and I wanted to use the Navbar provided by React-Bootstrap.
I created a Navigation.js file containing a class Navigation to separate the Navbar and the Routing from the App.js file. However, both parts do not seem to work. When I load the page, it is just empty, there is no Navbar. Can anyone spot a mistake?
Navigation.js:
import React, { Component } from 'react';
import { Navbar, Nav, Form, FormControl, Button, NavItem } from 'react-bootstrap';
import { Switch, Route } from 'react-router-dom';
import { Home } from './Page';
class Navigation extends Component {
render() {
return (
<div>
<div>
<Navbar>
<Navbar.Brand href="/">React-Bootstrap</Navbar.Brand>
<Navbar.Collapse>
<Nav className="mr-auto">
<NavItem eventkey={1} href="/">
<Nav.Link href="/">Home</Nav.Link>
</NavItem>
</Nav>
<Form inline>
<FormControl type="text" placeholder="Search" className="mr-sm-2" />
<Button variant="outline-success">Search</Button>
</Form>
</Navbar.Collapse>
</Navbar>
</div>
<div>
<Switch>
<Route exact path='/' component={Home} />
<Route render={function () {
return <p>Not found</p>
}} />
</Switch>
</div>
</div>
);
}
}
export default Navigation;
App.js:
import React, { Component } from 'react';
import Navigation from './components/routing/Navigation';
class App extends Component {
render() {
return (
<div id="App">
<Navigation />
</div>
);
}
}
export default App;
I tried using a NavItem containing a LinkContainer from react-router-bootstrap already, which led to the same result.
Just for completeness, Page.js:
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
export const Page = ({ title }) => (
<div className="App">
<div className="App-header">
<h2>{title}</h2>
</div>
<p className="App-intro">
This is the {title} page.
</p>
<p>
<Link to="/">Home</Link>
</p>
<p>
<Link to="/about">About</Link>
</p>
<p>
<Link to="/settings">Settings</Link>
</p>
</div>
);
export const About = (props) => (
<Page title="About"/>
);
export const Settings = (props) => (
<Page title="Settings"/>
);
export const Home = (props) => (
<Page title="Home"/>
);

First of all, in your snippets it doesn't seem like you're wrapping your code in a Router, so you should make sure that you're doing that inside App or in ReactDOM.render:
import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
rootElement
);
Next, your specific problem is that you're rendering react-bootstrap's Nav.Link instead of react-router's Link component, so the router is not picking up your route changes. Fortunately, react-bootstrap provides a render prop in most of its components to specify which component or element you want to render if you don't want the default. Switch to something like this:
import { Switch, Route, Link } from 'react-router-dom';
class Navigation extends Component {
render() {
return (
<div>
<div>
<Navbar>
<Navbar.Brand as={Link} to="/" >React-Bootstrap</Navbar.Brand>
<Navbar.Collapse>
<Nav className="mr-auto">
<NavItem eventkey={1} href="/">
<Nav.Link as={Link} to="/" >Home</Nav.Link>
</NavItem>
</Nav>
<Form inline>
<FormControl type="text" placeholder="Search" className="mr-sm-2" />
<Button variant="outline-success">Search</Button>
</Form>
</Navbar.Collapse>
</Navbar>
</div>
<div>
<Switch>
<Route exact path='/' component={Home} />
<Route render={function () {
return <p>Not found</p>
}} />
</Switch>
</div>
</div>
);
}
}

For those who have a problem with styling Link component from react-router-dom in react-bootstrap navbar, simply add className="nav-link", like this:
<Link to="/" className="nav-link">Home</Link>
instead of
<Nav.Link href="/">Home</Nav.Link>

I hope I'm no late to help some other people trying to solve this.
You can use the NavLink, instead of as={Link}. It will render with the same behavior of Link, but will "watch" the router URL to define which link is indeed active:
<Nav defaultActiveKey="/bills" as="ul">
<Nav.Item as="li">
<Nav.Link as={NavLink} to="/bills">Dividas</Nav.Link>
</Nav.Item>
<Nav.Item as="li">
<Nav.Link as={NavLink} to="/other">Em construção</Nav.Link>
</Nav.Item>
</Nav>

import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);
and Navbar.js:
import React from 'react';
import {Container,Navbar,Nav,NavItem } from 'react-bootstrap';
import {Link} from 'react-router-dom';
<Nav className="ml-auto">
<NavItem> <Link className="nav-link" to="/">Home</Link> </NavItem>
<NavItem> <Link className="nav-link" to="/about">About</Link> </NavItem>
<NavItem> <Link className="nav-link" to="/contact">Contact</Link> </NavItem>
</Nav>
This resolved the: <Link> outside a <Router> error for me.

Having found myself with a project of non-trivial size, and one that already had jQuery as a dependency I was able to gracefully solve the react-router / react-bootstrap mismatch with an event listener on the document.
This has one advantage over other solutions in that it requires no changes to the current markup. However, one may need to write some additional logic guarding the history.push call depending on needs. One may also need to expand this to guard for the target attribute, e.g. target="_blank".
If jQuery is not desired, one may be able to write a vanilla JS implementation with document.addEventListener without much additional effort.
// react-router#5
// usage of history may vary depending on version
import { Router } from 'react-router-dom';
import { createBrowserHistory } from 'history';
const history = createBrowserHistory();
// IIFE scoping jQuery for us
(($) => {
// Wait for document ready
$(() => {
$(document).on('click', '[href]', (event) => {
// Only target links targeting our application's origin
if (event.currentTarget.href.indexOf(window.location.origin) === 0) {
// Prevent standard browser navigation
event.preventDefault();
const path = event.currentTarget.href.slice(window.location.origin.length);
history.push(path);
}
});
});
})(jQuery);
const Routing = (props) => (
<Router history={ history }>
...
</Router>
);

Currently, with react v18 and react-router v6.4, the approach is working for me is a bit different.
To make the links properly work with react-route use as={Link} in the Nav.Link item.
And to make the tabs highlight you need to use eventKey as described in the documentation: EventKey is used to determine and control the active state of the parent Nav
Here is an example.
Notice that the changes also affect the Navbar.Brand component.
import { Link, useLocation } from 'react-router-dom';
const AppNavbar = () => {
const location = useLocation();
const activeKey = location.pathname === '/' ? '/projects' : location.pathname;
return (
<Navbar expand="lg" className="theme-navbar">
<Container>
<Navbar.Brand as={Link} to="/">
My Projects
</Navbar.Brand>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav activeKey={activeKey} className="me-auto">
<Nav.Link as={Link} eventKey="/projects" to="/projects">
Projects
</Nav.Link>
<Nav.Link as={Link} eventKey="/work" to="/work">
Ongoing Tasks
</Nav.Link>
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
);
};

i think you forgot to include bootstrap css, refer to the stylesheets section of the following doc
https://react-bootstrap.github.io/getting-started/introduction/
or just add the following to ur index.html
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css"
integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS"
crossorigin="anonymous"
/>

Related

Nav Link not rerendering page when clicked. Force update freezes page

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.
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;
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.

Login page and NavBar formatted with Reactstrap (Vertical and with custom background and text color)

I'm trying to make a login page , which would let me access me to the main site with displays a NavBar. I'm using ReactStrap, and I can't find the way of making the NavBar vertical instead of horizontal, neither setting the background and text colours and images. I could achieve to make a conditional rendering (to let administrator users to access some funcionalities like adding products, other users, and make puchrases, while sellers users are only allowed to make sales and view the sales registers).
Here's my code:
App.js:
import React from 'react';
import "./bootstrap.app.css";
import { BrowserRouter as Router, Route} from "react-router-dom";
import Example from "./componentes/navbar.componente"
import RegistroVentas from "./componentes/registro-ventas.componente";
import EditarVenta from "./componentes/editar-venta.componente";
import VenderProducto from "./componentes/realizar-venta.componente";
import NuevoUsuario from "./componentes/nuevo-usuario.componente";
import NuevoProducto from "./componentes/nuevo-producto.componente";
import ComprarProducto from "./componentes/realizar-compra.componente";
function App() {
return (
<Router>
<div className="container">
<Example />
<br/>
<Route path="/" exact component={RegistroVentas} />
<Route path="/registroVentas" component={RegistroVentas} />
<Route path="/editar/:id" component={EditarVenta} />
<Route path="/venta" component={VenderProducto} />
<Route path="/nuevoUsuario" component={NuevoUsuario} />
<Route path="/nuevoProducto" component={NuevoProducto} />
<Route path="/compra" component={ComprarProducto} />
</div>
</Router>
);
}
export default App;
navbar.js:
import React from 'react';
import {
Collapse,
Navbar,
NavbarToggler,
NavbarBrand,
Nav,
Badge,
NavItem,
NavLink,
UncontrolledDropdown,
DropdownToggle,
DropdownMenu,
DropdownItem } from 'reactstrap';
//import FontAwesome from '#fortawesome/react-fontawesome';
//import 'Ventas' from './ventas-cod'
class Ventas extends React.Component {
render() {
return(
<NavItem>
<NavLink href="/venta">
<Badge pill color="dark">Venta</Badge>
</NavLink>
</NavItem>
);
}
}
class Compra extends React.Component {
render() {
return(
<NavItem>
<NavLink href="/compra">
<Badge pill color="dark">Compra</Badge>
</NavLink>
</NavItem>
);
}
}
class Altas extends React.Component {
render () {
return(
<UncontrolledDropdown nav inNavbar>
<DropdownToggle nav caret>
<Badge pill color="dark">Altas</Badge>
</DropdownToggle>
<DropdownMenu right>
<DropdownItem>
<NavLink href="/nuevoUsuario">
<Badge pill color="dark">Usuario</Badge>
</NavLink>
</DropdownItem>
<DropdownItem>
<NavLink href="/nuevoProducto">
<Badge pill color="dark">Producto</Badge>
</NavLink>
</DropdownItem>
<DropdownItem divider />
<DropdownItem>
Reset
</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
);
}
}
export default class Example extends React.Component {
constructor(props) {
super(props);
this.tipoUsuario='administrador';
this.toggle = this.toggle.bind(this);
this.state = {
isOpen: false
};
}
toggle() {
this.setState({
isOpen: !this.state.isOpen
});
}
render() {
return (
<div>
<Navbar color="green" expand="lg">
<NavbarBrand href="/">Supermercado Caplan</NavbarBrand>
<NavbarToggler vertical className="d-flex" onClick={this.toggle} />
<Collapse isOpen={this.state.isOpen} navbar>
<Nav className="d-flex ml-auto" >
<Ventas />
{this.tipoUsuario=='administrador' ?
<Compra /> : <a></a>
}
{this.tipoUsuario=='administrador' ?
<Altas /> : <a></a>
}
</Nav>
</Collapse>
</Navbar>
</div>lt
);
}
}
Here's what I'm getting:
Here's something I would like to get:
Does anyone have an idea of what should I do?
Thank's a lot!
In Reactstrap, there's no such a thing like a native component called Sidebar.
However, it's possible to download a template with a sidebar implemented, and then wrap the whole application into it.
For the login cuestion, there's a lot of examples on the web. While all of them should work correctly if implemented properly, I've chosen one of the simplest I found, which works fine for the kind of project I'm doing. However, while it allows me to login with my credentials into a local deployment, it isn't probably the best solution for an application deployed into a web service, since the security of the system it's not just a big deal for an app which is running into a local machine, just written for academic purposes.
So then, here's the template I've found for the Reactstrap sidebar and the login method in which I've based on to implement in my app, and also my app with both things implemented.
Sidebar template:
https://codesandbox.io/s/5ku6t
Login method used:
https://contactmentor.com/login-form-react-js-code/
App with login and sidebar implemented:
https://gitlab.com/leandrocaplan/supermercado-caplan-final-programacion-iii-inspt-utn
(See the frontend folder to see the implementation)
Notice that in my app, the way I've found to format the sidebar, and also the topbar, is creating my own CSS classes, and apply them into the sidebar and topbar components. These classes are found in the App.css file at the correspondent frontend directory.

react-router-dom doesn't work for my project

I installed react-router-dom to switch between navbar elements. The library does not want to cooperate with my project. After clicking on the navbar element I am not redirected to the required component. Sometimes when I click on a selected item the menu moves slightly to the left. My code looks like this:
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
ReactDOM.render(
<App />, document.getElementById('root'));
Navbar.js
import React, { useState } from "react";
import App from '../components/App'
import About from '../components/About';
import Services from '../components/Services';
import Contact from '../components/Contact';
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
const Navbar = () => {
const [navLinkOpen, navLinkToggle] = useState(false);
const handleNavLinksToggle = () => {
navLinkToggle(!navLinkOpen);
};
const renderClasses = () => {
let classes = "navlinks";
if(navLinkOpen) {
classes += " ' ' + active";
}
return classes;
};
return (
<nav>
<div className="logo">
<h4>Delightartco</h4>
</div>
<ul className={renderClasses()}>
<Router>
<li className="link"><Link to={"/home"}>Home</Link></li>
<li className="link"><Link to={"/about"}>About</Link></li>
<li className="link"><Link to={"/services"}>Services</Link></li>
<li className="link"><Link to={"/contact"}>Contact</Link></li>
<Switch>
<Route path="/home" component={App}>
</Route>
<Route path="/about" component={About}>
</Route>
<Route path="/services" component={Services}>
</Route>
<Route path="/contact" component={Contact}>
</Route>
</Switch>
</Router>
</ul>
<div onClick={handleNavLinksToggle} className="hamburger-toggle">
<i className="fas fa-bars fa-lg"></i>
</div>
</nav>
)
}
export default Navbar;
App.js
import React from 'react';
import '../../src/App.css';
import Navbar from './Navbar';
import Wrapper from './Wrapper';
import {Content, Winnie, Testimonials, Values, Secrets, Footer} from '../components/Content';
function App() {
return (
<div>
<Navbar />
<Wrapper />
<Content />
<Winnie />
<Testimonials />
<Values />
<Secrets />
<Footer />
</div>
)
}
export default App;
These are few issues in your code:
App is your root React component, and you gave it a route: <Route path="/home" component={App}></Route>. This is causing a recursive / infinite loop. App component inside App component.
Code structure looks complex.
Here is a proposed fixed code:
index.jsx:
ReactDOM.render(<App />, document.getElementById("root"));
App.jsx:
export default function App() {
return (
<StrictMode>
<Routes />
</StrictMode>
);
}
Routes.jsx:
export default function Routes() {
return (
<Router>
{/* Route components would be visible only at their route */}
<Switch>
<Route exact path="/about" component={About}></Route>
<Route exact path="/services" component={Services}></Route>
<Route exact path="/contact" component={Contact}></Route>
</Switch>
{/* Below components would be visible always at UI */}
<Navbar /> {/* Top navigation Link's */}
<Wrapper />
<Content />
<Winnie />
<Testimonials />
<Values />
<Secrets />
<Footer /> {/* Bottom navigation Link's */}
</Router>
);
}
There are several things to keep in mind when using react-router.
The Router or BrowserRouter component should wrap all your routes and your links. Generally, if your app does not need more than one Router, its better to wrap your whole App with the Router.
The Link component's job is to simply navigate to the page and can be used anywhere you want to show a link to someplace e.g. in the Navbar.
The Route (not Router) component's placement is very important. It should be placed where you want to render the content. In your code you are rendering the routes in the Navbar and are unable to see the routes being rendered due to invalid / improper structure.
Navbar.js
Your Navbar should only contain the links while the Router should be on the top-level and the Switch / Routes should be placed where you want to render the content.
function Navbar() {
return (
<nav>
{/* Move `Router` to top-level e.g. in App.js */}
<ul>
<li className="link">
<Link to={"/home"}>Home</Link>
</li>
<li className="link">
<Link to={"/about"}>About</Link>
</li>
<li className="link">
<Link to={"/services"}>Services</Link>
</li>
<li className="link">
<Link to={"/contact"}>Contact</Link>
</li>
</ul>
{/* Move `Switch and Routes` to where you want to render the content e.g. in Content.js */}
</nav>
);
}
App.js
function App() {
return (
<Router>
<div>
<Navbar />
<Wrapper />
<Switch>
<Route path="/home" component={App}></Route>
<Route path="/about" component={About}></Route>
<Route path="/services" component={Services}></Route>
<Route path="/contact" component={Contact}></Route>
</Switch>
<Winnie />
<Testimonials />
<Values />
<Secrets />
<Footer />
</div>
</Router>
);
}

React scroll with redirect to other route path

I have a problem with my page that I build. There is main route path like "/" where is all page but there is also route path "/privacy" where you can go by clicking button "Privacy policy". Main navigation and footer with navigation are displaying at "/" and "/privacy" also.
It looks like this:
<Route exact path="/">
<Header />
<Main />
<Footer />
</Route>
<Route path="/privacy">
<Header />
<Privacy />
<Footer />
</Route>
The Main component looks like this
const Main = () => {
return (
<>
<Hello />
<Services />
<Projects />
<About />
<Contact />
</>
)}
All buttons in nav are react-scroll links.
<ul>
<li><Link to="header" smooth="true" duration={1000}>Main</Link></li>
<li><Link to="services" smooth="true" duration={1000}>Services</Link></li>
<li><Link to="webdev" smooth="true" duration={1000}>Portfolio</Link></li>
<li><Link to="about" smooth="true" duration={1000}>About</Link></li>
<li><Link to="contact" smooth="true" duration={1000}>Contact</Link></li>
</ul>
How can I redirect user from "/privacy" and scroll to - for example - about component at my "/" route path when he clicks "About" button in nav?
Example:
User is at "/privacy" and he wants to read "About" section, so he clicks button "About" in nav and then website is redirecting to "/" and scrolling to "About" section.
So. Add to component / root element of component about id="about" and then in your link set path <Link to="/#about"......
You can find info how to make links to content on the same page here (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a)
I used HashLink from the library react-router-hash-link. I simulated the home sections with two components Component1 and Component2 in order to make it more generic.
It's necessary install two packages
npm install react-router-dom
npm install react-router-hash-link
Here is the code:
Set the routes in the App.jsx
App.jsx
import React from "react";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import { Home } from "./components/Home";
import { Component0 } from "./components/Component0";
function App() {
return (
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/component0" element={<Component0 />} />
</Routes>
</Router>
);
}
export default App;
Home contains Component1 and Component2 and a button for navigating to Component0
Home.jsx
import React from 'react';
import { Component1 } from './Component1';
import { Component2 } from './Component2';
import { HashLink } from 'react-router-hash-link';
export const Home = props =>
{
return (<>
<HashLink to="/component0">
<button>Button component 0</button>
</HashLink>
<Component1/>
<Component2/>
</>);
}
The Component0 is a separated section from which we can navigate to Component1 or Component2 by scrolling within the Home component. To navigate we use the HashLink with a wrapped button
Component.jsx
import React from 'react';
import { HashLink } from 'react-router-hash-link';
export const Component0 = props =>
{
return (<>
<HashLink smooth to="/#section-component1">
<button>Component1</button>
</HashLink>
<HashLink smooth to="/#section-component2">
<button>Component2</button>
</HashLink>
</>);
}
Component1 and Component2
Component1.jsx
import React from 'react';
import "./Component1.css"
export const Component1 = props =>
{
return (<>
<section id="section-component1">
<h1>Section of component 1</h1>
</section>
</>);
}
Component2.jsx
import React from 'react';
import "./Component2.css"
export const Component2 = props =>
{
return (<>
<section id="section-component2">
<h1>Section of component 2</h1>
</section>
</>);
}
Repo: https://github.com/JCaeta/react-navigation

Can you separate Links and Routes in separate JS files?

I have a Nav.js file and an App.js file
Nav.js -
import { Link, Router } from 'react-router-dom'
render() {
return (
<Router>
<ul className="nav-list">
<li><Link to="/">Home<Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/contact">Contact</Link></li>
</ul>
</Router>
)
}
App.js -
import Nav from './nav.js'
import { BrowserRouter as Router, Route, Switch } from "react-router-dom"
render() {
return (
<Nav />
<Router>
<Switch>
<Route exact path="/" />
<Route exact path="/about" />
<Route exact path="/contact" />
</Switch>
</Router>
)
}
This doesn't work for some reason, but I feel like it should based off the react-router-dom docs. React Router seems like it should be simple but I'm having a hard time with the learning curve. I can't really get things to work the way I want them to. Does anyone know how it can be setup this way or have a good reference to clarify some things up for me?
You can address this issue in two files
but within the same BrowserRouter tags you have missed this in your given sample. It should be,
import Nav from './nav.js'
import { BrowserRouter, Route, Switch } from "react-router-dom"
render() {
return (
<BrowserRouter>
<Nav />
<Switch>
<Route exact path="/" />
<Route exact path="/about" />
<Route exact path="/contact" />
</Switch>
</BrowserRouter>
)
}
hope this will help you.
In an app created by create-react-app (I am using reactstrap, but you can remove it and do without it):
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import Nav from './components/Navigation'; // top (fixed) navigation
import Footer from './components/Footer'; // bottom (fixed) footer
import Home from './components/Home';
import One from './components/One';
import Two from './components/Two';
...
ReactDOM.render(
<Provider store={store}>
<div>
<BrowserRouter>
<div>
<Route path="/" component={Navigation} />
<Switch>
<Route exact path="/" component={Home} />
<Route path="/one" component={One} />
<Route path="/two" component={Two} />
</Switch>
<Footer />
</BrowserRouter>
</div>
</Provider>
, document.querySelector('#root'));
Navigation.js:
import React from 'react';
import { Collapse, Navbar, NavbarToggler, NavbarBrand, Nav, NavItem, NavLink } from 'reactstrap';
import { Link } from 'react-router-dom';
class Navigation extends React.Component {
constructor(props) {
super(props);
this.toggle = this.toggle.bind(this);
this.state = {
isOpen: false
};
}
toggle() {
this.setState({
isOpen: !this.state.isOpen
});
}
render() {
return (
<div>
<Navbar color="faded" light expand="md">
<NavbarBrand tag={Link} to="/">
<img src="/assets/images/book_lover.png" alt="book-lover!" />
</NavbarBrand>
<Nav className="ml-auto" navbar>
<NavItem>
<NavLink tag={Link} to="#">
</NavLink>
</NavItem>
</Nav>
<NavbarToggler onClick={this.toggle} />
<Collapse isOpen={this.state.isOpen} navbar>
<Nav className="ml-auto" navbar>
{this.props.loginEmail && <NavItem>
<NavLink tag={Link} to="/cats">Book-Categories</NavLink>
</NavItem>}
<NavItem>
<NavLink tag={Link} to="/howto">How-To-Use-This-Site</NavLink>
</NavItem>
<NavItem>
<NavLink tag={Link} to="/about">About</NavLink>
</NavItem>
</Nav>
</Collapse>
</Navbar>
<hr />
</div>
);
}

Categories