React-router v.4 - Links in header doesn't work - reactjs

I'm using react-router v.4 in my React app and have faced with this trouble: when I click at <Link> component, the URL is changing, but data is not rendering.
Here is my code snippets:
Header.component.js:
import React from 'react';
import Navbar from 'react-bootstrap/lib/Navbar';
import Nav from 'react-bootstrap/lib/Nav';
import NavItem from 'react-bootstrap/lib/NavItem';
import NavDropdown from 'react-bootstrap/lib/NavDropdown';
import MenuItem from 'react-bootstrap/lib/MenuItem';
import {Link} from 'react-router-dom';
//utils
import History from '../../utils/History';
import bindAll from 'lodash/bindAll';
class Header extends React.Component {
constructor(props) {
super(props);
bindAll(this, '_getHeaderItem');
}
_getHeaderItem() {
switch (History.location.pathname) {
case '/sign-in':
return <li><Link to='/sign-up'>Sign Up</Link></li>;
break;
case '/sign-up':
return <li><Link to='/sign-in'>Sign In</Link></li>;
break;
default:
return null;
}
}
render() {
return (
<Navbar collapseOnSelect>
<Navbar.Header>
<Navbar.Brand>
Elevator
</Navbar.Brand>
<Navbar.Toggle />
</Navbar.Header>
<Navbar.Collapse>
<Nav>
<NavItem eventKey={1} href="#">Link</NavItem>
</Nav>
<Nav pullRight>
{this._getHeaderItem()}
<NavDropdown eventKey={4} id='member-dropdown' title={
<div className='inline-block'>
<img src='' alt='' />
Username
</div>
}>
<MenuItem eventKey={4.1}>My profile</MenuItem>
<MenuItem eventKey={4.2}>Logout</MenuItem>
<MenuItem divider />
<MenuItem eventKey={4.3}>Administration</MenuItem>
</NavDropdown>
</Nav>
</Navbar.Collapse>
</Navbar>
);
}
}
export default Header;
app.js: (which is collecting all components and has routing logic)
import React from 'react';
import ReactDOM from 'react-dom';
import fetch from 'whatwg-fetch';
import { Router, Route, Redirect } from 'react-router';
//utils
import History from './utils/History';
//components
import App from './common/components/App.component';
import SignUp from './modules/signUp/SignUp.component';
import SignIn from './modules/signIn/SignIn.component';
import Footer from './modules/footer/Footer.component';
//styles
require ('./../styles/main.scss');
let loggedIn = localStorage.getItem('token');
loggedIn ? History.replace('/dashboard') : History.replace('/sign-in');
ReactDOM.render(
<Router history={History}>
<App>
<Route path='/sign-in' render={() => (
loggedIn ? (
<Redirect to="/dashboard" />
) : (
<SignIn />
)
)} />
<Route path='/sign-up' render={() => (
loggedIn ? (
<Redirect to="/dashboard" />
) : (
<SignUp />
)
)} />
</App>
</Router>,
document.getElementById('app'));
ReactDOM.render(<Footer />, document.getElementById('footer'));
Temporary, I've done it with click handling (prevent default behavior and window.location.reload('some/path')), but it's not a React way.
I'll appreciate any advice.

Related

Page is not redirecting in reactjs but browser URL changes

I have below react-js code, which written for showing the navigation bar
When I click the links, the browser address changes BUT redirection is not happening
import React from "react";
import Navbar from "react-bootstrap/Navbar";
import { Nav } from "react-bootstrap";
import "bootstrap/dist/css/bootstrap.min.css";
import {
HomeRounded,
SchoolRounded,
WorkRounded,
Facebook,
Twitter,
LinkedIn,
GitHub,
Telegram,
} from "#mui/icons-material";
import { Link, NavLink, withRouter } from "react-router-dom";
import resumeData from "../../utils/resumeData";
import CustomButton from "../Button/Button";
import "./Header.css";
const Header = (props) => {
const pathName = props?.location?.pathname;
console.log(pathName);
return (
<Navbar expand="lg" sticky="top" className="header">
<Nav.Link as={NavLink} to="/">
<Navbar.Brand className="header_home">
<HomeRounded />
</Navbar.Brand>
</Nav.Link>
<Navbar.Toggle />
<Navbar.Collapse>
<Nav>
<Nav.Link
as={NavLink}
to="/"
className={pathName == "/" ? "header_link_active" : "header_link"}>
Resume
</Nav.Link>
<Nav.Link
as={NavLink}
to="/portfolio"
className={
pathName == "/portfolio" ? "header_link_active" : "header_link"}>
Portfolio
</Nav.Link>
</Nav>
</Navbar.Collapse>
</Navbar>
);
};
export default withRouter(Header);
Here is my App.js
import React from "react";
import { BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
import {Container, Grid } from "#material-ui/core";
import Profile from "./components/Profile/Profile";
import Header from "./components/Header/Header";
import Portfolio from "./pages/Portfolio/Portfolio";
import Resume from "./pages/Resume/Resume";
import Footer from "./components/Footer/Footer";
function App() {
return (
<Container className={'top_60'}>
<Grid container spacing={7}>
<Grid item xs={12} sm={12} md={4} lg={3}>
<Profile/>
</Grid>
<Grid item xs>
<Router>
<Header/>
<Switch>
<Route path="/portfolio">
<Portfolio />
</Route>
<Route path="/">
<Resume />
</Route>
</Switch>
</Router>
<Footer/>
</Grid>
</Grid>
</Container>
);
}
export default App;
It works fine ONLY when I manually click ENTER on browser URL!
here is the error in console
on app.js you have to declare the routes on this way:
<Route path="/" element={<Home />} />

My React Component is rendering twice and then getting redirected to homepage

I am learning reactjs and creating a test quiz project with it. The plan is only logged-in users will be able to access a quiz.
I am using react-router. When I have already accessed the website and then accessing different pages, it's not causing any problem. but when I am trying to access a route directly, the component of that route is rendering twice and then getting redirected to the home page. To clarify the situation with an example, I have a route /quiz. when I visit http://localhost:3000/quiz directly in the browser, it prints the following message in the console.
[HMR] Waiting for update signal from WDS...
Quiz.js:10 Quiz rendered
Quiz.js:10 Quiz rendered
app.js:5 works
then I am being redirected to http://localhost:3000/.
So, my problems are:
I am getting rendered twice
I am being redirected.
I have attached the route and quiz component here. What is causing the issue?
Routes.js
import React, {useState} from 'react'
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'
import Home from '../public_page_components/Home'
import About from '../public_page_components/About'
import SearchPage from '../product_search_components/SearchPage'
import NoMatch from '../public_page_components/NoMatch'
import MyNav from './MyNav'
import Todo from '../public_page_components/Todo'
import Quiz from '../public_page_components/Quiz'
import Footer from '../public_page_components/Footer'
export default function Routes(props) {
var isSigned = localStorage.getItem('scs_user_logged_in') ? true : false
const [signedIn, setSignedIn] = useState(isSigned)
return (
<Router>
<MyNav signedIn={signedIn} setSignedIn={setSignedIn} search_item={props.search_item} setSearchItem={props.setSearchItem}/>
<Switch>
<Route path='/' exact>
<Home search_item={props.search_item} setSearchItem={props.setSearchItem} />
</Route>
<Route path='/about' exact component={About} />
<Route path='/search/:search_term' children={<SearchPage search_item={props.search_item} setSearchItem={props.setSearchItem}/>} />
<Route path="/todo" exact>
<Todo/>
</Route>
<Route path="/quiz" exact>
<Quiz signedIn={signedIn} setSignedIn={setSignedIn}/>
</Route>
<Route path="*" component={NoMatch} />
</Switch>
<Footer/>
</Router>
)
}
Quiz.js
import React from 'react'
import Button from 'react-bootstrap/Button'
import Row from 'react-bootstrap/Row'
import Col from 'react-bootstrap/Col'
export default function Quiz(props) {
console.log('Quiz rendered')
let quiz_menu = props.signedIn ? <div style={{textAlign:"right"}}>Logged in</div> : "not logged in"
return (
<>
<div style={{minHeight:"80vh"}}>
<Row>
<Col>
<h1>
Quiz
</h1>
</Col>
<Col style={{display:"flex", alignItems:"center"}}>
{quiz_menu}
</Col>
</Row>
<Row style={{margin:"5px 0px"}}>
<Col xs={9} style={{backgroundColor:"blue"}}>
test
</Col>
<Col xs={3} style={{backgroundColor:"red"}}>
test
</Col>
</Row>
</div>
</>
)
}
MyNav.js
import React from 'react'
import Nav from 'react-bootstrap/Nav'
import Navbar from 'react-bootstrap/Navbar'
// import NavDropdown from 'react-bootstrap/NavDropdown'
import { Link } from 'react-router-dom'
import Searchfield from '../product_search_components/Searchfield'
import LoginSignout from '../login_components/LoginSignout'
import MenuButtons from './MenuButtons'
export default function MyNav(props) {
var menu = props.signedIn ? <LoginSignout setSignedIn={props.setSignedIn}/> : <MenuButtons setSignedIn={props.setSignedIn}/>
return (
<Navbar bg="dark" variant="dark" expand="lg">
<Navbar.Brand><span style={{ fontWeight: 'bold' }}>Test</span></Navbar.Brand>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="mr-auto">
<Link className='nav-link' to="/">Home</Link>
<Link className='nav-link' to="/about">About</Link>
<Link className='nav-link' to="/todo">Todo</Link>
<Link className='nav-link' to="/quiz">Quiz</Link>
{/* <NavDropdown title="Dropdown" id="basic-nav-dropdown">
<NavDropdown.Item>Action</NavDropdown.Item>
<NavDropdown.Item>Another action</NavDropdown.Item>
<NavDropdown.Item>Something</NavDropdown.Item>
<NavDropdown.Divider />
<NavDropdown.Item>Separated link</NavDropdown.Item>
</NavDropdown> */}
</Nav>
</Navbar.Collapse>
<Searchfield search_item={props.search_item} setSearchItem={props.setSearchItem} />
{menu}
</Navbar>
)
}

React router not rendering components anymore except the default one

I took a break from my project for a day and today I come back to and suddenly i have an issue with my react router. I was messing around with adding more components but deleted them and now my Homepage, about, or gallery component dont render when I change the page with then navbar. The url still changes if i click on gallery to /gallery but the <h1>Gallery page</h1> does not show up anymore.
App.js
import React, { Component } from 'react';
import './App.css';
import NavigationBar from './components/navbar';
import About from './components/About';
import Home from './components/homepage';
import Gallery from './components/gallery';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
class App extends Component {
state = {};
render() {
return (
<Router>
<div className="App">
<NavigationBar />
<Switch>
<Route path="/" exact component={Home} />
<Route path="/about" component={About} />
<Route path="/gallery" component={Gallery} />
</Switch>
</div>
</Router>
);
}
}
export default App;
Homepage
import '../css/homepage.scss';
class Homepage extends Component {
state = {};
render() {
return (
<div>
<h1>Hello</h1>
</div>
);
}
}
export default Homepage;
About
class About extends Component {
state = {};
render() {
return <h1>About</h1>;
}
}
export default About;
Gallery
class gallery extends Component {
state = {};
render() {
return <h1>Gallery page</h1>;
}
}
export default gallery;
Nav code
import React, { Component } from 'react';
import Navbar from 'react-bootstrap/Navbar';
import Nav from 'react-bootstrap/Nav';
import { link } from 'react-router-dom';
import { NavLink } from 'react-router-dom';
import '../css/navbar.scss';
import $ from 'jquery';
import logo from '../images/logo.png';
class NavigationBar extends Component {
state = {};
render() {
return (
<Navbar fixed="top" className="navbarr" bg="light" expand="sm">
<Navbar.Brand
activeClassName="nav-link--active"
className="BrandLink"
href="/"
>
<img
alt=""
src={logo}
width="45"
height="30"
className="d-inline-block align-top"
/>
BRAND NAME HERE
</Navbar.Brand>
<Navbar.Toggle />
<Navbar.Collapse className="justify-content-end">
<Nav className="ml-auto">
<Nav.Link
className="NavLink"
activeClassName="nav-link--active"
href="/About"
>
About
</Nav.Link>
<Nav.Link
className="NavLink"
activeClassName="nav-link--active"
href="/Gallery"
>
Gallery
</Nav.Link>
</Nav>
</Navbar.Collapse>
</Navbar>
);
}
}
export default NavigationBar;
Try moving your default route to the end of routes. i.e.
import React, { Component } from 'react';
import './App.css';
import NavigationBar from './components/navbar';
import About from './components/About';
import Home from './components/homepage';
import Gallery from './components/gallery';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
class App extends Component {
state = {};
render() {
return (
<Fragment>
<div className="App">
<NavigationBar />
</div>
<Router>
<Switch>
<Route path="/about" component={About} />
<Route path="/gallery" component={Gallery} />
<Route path="/" component={Home} />
</Switch>
</Router>
</Fragment>
);
}
}
export default App;
The problem is with you Navbar components. Try this one:
import React, { Component } from "react";
import Navbar from "react-bootstrap/Navbar";
import Nav from "react-bootstrap/Nav";
import { Link } from "react-router-dom";
import "../css/navbar.scss";
import $ from "jquery";
import logo from "../images/logo.png";
class NavigationBar extends Component {
state = {};
render() {
return (
<Navbar fixed="top" className="navbarr" bg="light" expand="sm">
<Navbar.Brand activeClassName="nav-link--active" className="BrandLink">
<Link to="/">
<img
alt=""
src={logo}
width="45"
height="30"
className="d-inline-block align-top"
/>
BRAND NAME HERE
</Link>
</Navbar.Brand>
<Navbar.Toggle />
<Navbar.Collapse className="justify-content-end">
<Nav className="ml-auto">
<Nav.Link className="NavLink" activeClassName="nav-link--active">
<Link to="/about">About</Link>
</Nav.Link>
<Nav.Link className="NavLink" activeClassName="nav-link--active">
<Link to="/gallery">Gallery</Link>
</Nav.Link>
</Nav>
</Navbar.Collapse>
</Navbar>
);
}
}
export default NavigationBar;

"How to make a functional Navbar"

I'm fairly new to React and I'm trying to implement Navbar with react-bootstrap. I have the navigation bar set up but its not actually linking to any of my pages.
I've tried looking through the documentation but there's not much information there. I've looked at other posts but they all seem to be using older versions of react-bootstrap or not using it at all.
import React from "react";
import ReactDOM from "react-dom";
import "./components/stylesheets/index.css";
import * as serviceWorker from "./serviceWorker";
import "bootstrap/dist/css/bootstrap.min.css";
import App from "./App";
ReactDOM.render(<App />, document.getElementById("root"));
serviceWorker.unregister();
import React, { Component } from "react";
import "./components/stylesheets/App.css";
import NavBar from "./components/NavBar";
import Home from "./components/Home";
import About from "./components/About";
class App extends Component {
render() {
return <NavBar />;
}
}
export default App;
import React, { Component } from "react";
import { Navbar, Nav, Form, FormControl, Button } from "react-bootstrap";
import "./stylesheets/NavBar.css";
class NavBar extends Component {
state = {};
render() {
return (
<div id="bar">
<Navbar bg="light" variant="light">
<Navbar.Brand href="#home">CALC-U</Navbar.Brand>
<Nav className="ml-auto">
<Nav.Link href="#home">Home</Nav.Link>
<Nav.Link href="#about">About</Nav.Link>
<Nav.Link href="#updates">Updates</Nav.Link>
<Nav.Link href="#profile">Profile</Nav.Link>
</Nav>
</Navbar>
</div>
);
}
}
export default NavBar;
I want the app to open up to the Home page automatically, and then open up the other pages if the button is clicked on in the navBar.
Edit: I've created a working example, you can check the code: Codesandbox
Seems like you're not using react-router for handling the links.
First you need to wrap your component with a BrowserRouter like so:
import { BrowserRouter } from "react-router-dom";
import App from "./App";
const app = (
<BrowserRouter>
<App />
</BrowserRouter>
);
ReactDOM.render(app, document.getElementById("root"));
And in NavBar.js, inside a <Switch /> component, you declare the routes:
import { Switch, Route, Link } from "react-router-dom";
//(...)
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
</Switch>
In your case, you case use Link component inside your Nav.Link:
<Nav className="ml-auto">
<Nav.Link as={Link} to="/">Home</Nav.Link>
<Nav.Link as={Link} to="/about">About</Nav.Link>
</Nav>
Same applies if you want to add more links to the NavBar.
Sample application using react-bootstrap for Navbar
App.js
function App() {
return (
<div>
<Router>
<NavBar />
<Switch>
<Route path="/" exact component={Home} />
<Route path="/about" exact component={About} />
<Route path="/updates" exact component={Updates} />
<Route path="/profile" exact component={Profile} />
</Switch>
</Router>
</div>
);
}
const Home = () => <h1>Home</h1>;
const About = () => <h1>About</h1>;
const Updates = () => <h1>Updates</h1>;
const Profile = () => <h1>Profile</h1>;
NavBar.js
class NavBar extends React.Component {
state = {};
render() {
return (
<div id="bar">
<Navbar bg="light" variant="light">
<Navbar.Brand href="/">CALC-U</Navbar.Brand>
<Nav className="ml-auto">
<Nav.Link href="/">Home</Nav.Link>
<Nav.Link href="/about">About</Nav.Link>
<Nav.Link href="/updates">Updates</Nav.Link>
<Nav.Link href="/profile">Profile</Nav.Link>
</Nav>
</Navbar>
</div>
);
}
}

Reactjs - SPA Routing using a Navbar

Problem
I want to start off by saying that I am still new to reactjs and nodejs as a whole. I am working on a dynamic NavBar for a Single Page Application (SPA), but I am struggling with the routing. It took me some time, but I got the routing to work in general. For some reason, the "topics" and "about" pages will load properly (without reloading the whole page); however, the two reports (General Reports and International Reports) Nav options will reload the page with each click, defeating the purpose of a SPA. I looked through tutorial after tutorial just to get this far... I am hoping someone here can assist in pointing out what I am doing wrong.
The Code
This is the Navbar code:
import React from 'react';
import { render } from 'react-dom';
import { Navbar, Nav, NavItem, NavLink, MenuItem, NavDropdown } from 'react-bootstrap';
import { Router, Route, Switch } from 'react-router';
import { getUserGroup } from './Auth.jsx'; /*this is a mock file, the code only assigns a role that I can control by changing a "username"*/
var isDev = getUserGroup() === "dev" ? true : false;
var isAdmin = getUserGroup() === "admin" ? true : false;
var isDataAnalyst = getUserGroup() === "analyst" ? true : false;
/* setup this way intentionally to dynamically render the Navigation bar */
var renderUserVerify = !isDataAnalyst ? <MenuItem eventKey={1.1} href="/UserVerfication">USER VERIFICATION</MenuItem> : null;
var renderPkgLookup = !isDataAnalyst ? <MenuItem eventKey={1.2} href="/PkgInqueryn">PACKAGE INQUERY</MenuItem> : null;
var renderQuerySearch = !isDataAnalyst ? <NavDropdown eventKey={1} title="QUERY SEARCHES" id="query-nav-dropdown">
{renderUserVerify}
{renderPkgLookup}
</NavDropdown> : null;
var renderUpdateUser = isDev || isAdmin ? <NavItem eventKey={2} href="/UpdateUser">UPDATE USER</NavItem> : null;
var renderFPReports = isDev || isAdmin || isDataAnalyst ? <MenuItem eventKey={3.1} href="/reports/GenReports">GENERAL REPORTS</MenuItem> : null;
var renderIntlReports = isDev || isAdmin || isDataAnalyst ? <MenuItem eventKey={3.2} href="/reports/IntlReports">INTERNATIONAL REPORTS</MenuItem> : null;
var renderReports = isDev || isAdmin || isDataAnalyst ? <NavDropdown eventKey={3} title="REPORTS" id="reports-nav-dropdown">
{renderGenReports}
{renderIntlReports}
</NavDropdown> : null;
var renderUserPref = !isDataAnalyst ? <NavItem eventKey={4} href="/UserPref">USER PREFERENCE</NavItem> : null;
export default class Navigation extends React.Component {
handleSelect(eventKey) {
/*event.preventDefault();*/
this.state.href
}
render() {
return (
<div>
<Navbar inverse fluid collapseOnSelect>
<Navbar.Header>
<Navbar.Brand>
CPMS
</Navbar.Brand>
<Navbar.Toggle />
</Navbar.Header>
<Navbar.Collapse>
<Nav onSelect={c => this.handleSelect(c)}>
{renderQuerySearch}
{renderUpdateUser
{renderReports}
{renderUserPref}
<NavItem eventKey={5} href="/Help">HELP</NavItem>
<NavItem eventKey={6} href="/logout">LOGOUT</NavItem>
</Nav>
</Navbar.Collapse>
</Navbar>
</div>
);
}
}
This is the routing code:
import React from "react";
import { BrowserRouter as Router, Route, Link, HashRouter, NavLink } from "react-router-dom";
import GenReports from '../pages/GenReports';
import IntlReports from '../pages/IntlReports';
const BodyContent = () => (
<Router>
<div>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} /> /* dummy page for testing routing */
<Route path="/topics" component={Topics} /> /* dummy page for testing routing */
<Route path="/Reports/GenReports" component={GenReports} />
<Route path="/Reports/IntlReports" component={IntlReports} />
</div>
</Router>
);
const Home = () => (
<div>
<h2>This is the home page</h2>
</div>
);
const About = () => (
<div>
<h2>About</h2>
</div>
);
const Topics = ({ match }) => (
<div>
<h2>Topics</h2>
<NavLink to={`${match.url}/rendering`}>Rendering with React</NavLink><br />
<NavLink to={`${match.url}/components`}>Components</NavLink><br />
<NavLink to={`${match.url}/props-v-state`}>Props v. State</NavLink><br />
<Route path={`${match.url}/:topicId`} component={Topic} />
<Route
exact
path={match.url}
render={() => <h3>Please select a topic.</h3>}
/>
</div>
);
const Topic = ({ match }) => (
<div>
<h3>{match.params.topicId}</h3>
</div>
);
export default BodyContent;
This is the code for the App.js
import React, { Component } from 'react';
import Navigation from './components/NavComponent';
import BodyContent from './components/RoutingComponent';
import 'react-bootstrap';
import logo from './logo.svg';
import './App.css';
export default class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<Navigation />
<BodyContent />
</div>
);
}
}
This is the GenReports page (the other reports page is setup the same way)
import React from 'react';
export default class IntlReports extends React.Component {
render() {
return (
<h1>You have reached the General Reports Page</h1>
);
}
}

Resources