I am a noob just started learning React a few days ago. I have a problem while I was working with react router v4.
I have a home page component, like this:
import React, {Component} from 'react';
class AboutPage extends Component {
render() {
return (
<div>
<h1>About</h1>
<p>this is the about page</p>
</div>
);
}
}
export default AboutPage;
and here is the App.js:
import React, { Component } from 'react';
import './App.css';
import {
Link, Route, Switch,BrowserRouter
} from 'react-router-dom'
import Header from './components/common/Header';
import HomePage from './components/home/HomePage';
import AboutPage from './components/about/AboutPage';
class App extends Component {
render() {
const home = () =><h1> Home </h1>
const about = () =><h1> about </h1>
return (
<BrowserRouter>
<div className="container-fluid">
<Header/>
<Switch>
<Route exact path="/" components={home}/>
<Route path="/about" components={about}/>
</Switch>
</div>
</BrowserRouter>
);
}
}
export default App;
the headers file is just a nav element I want it for all the component.
The problem is if I click either homepage or about page, it doesn't display the content of these components. It just shows the nav element and that's all.
I built this app using creat-react-app. Is there anything wrong in my code? Thx.
Reading the docs looks like that the Route component is expecting the property component and not components. I also believe that what you want to render is your HomePage and AboutPage component
Related
I have been receiving white blank pages when trying to create multiple pages within my app and I have been using the router-dom to try and fix this but still can't understand why. Here is my code with Home and Navigation js being inside a components folder in the src directory and App.js just inside the src directory.
App.js
import React, { Component } from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import Home from './components/Home';
import Glazing from './components/Glazing';
import Navigation from './components/Navigation';
class App extends Component {
render() {
return (
<BrowserRouter>
<div>
<Navigation />
<Route path="/" component={Home} exact/>
<Route path="/glazing" component={Glazing}/>
</div>
</BrowserRouter>
);
}
}
export default App;
Nav.js
import React from 'react';
import { NavLink } from 'react-router-dom';
const Navigation = () => {
return (
<div>
<NavLink to="/">Home</NavLink>
<NavLink to="/glazing">Glazing</NavLink>
</div>
);
}
export default Navigation;
Home.js
import React from "react";
import logo from '../logo.svg';
import './Home.css';
import "#fontsource/dm-sans";
function home() {
return (
<div className="Home">
<header className="Home-header">
<h1>EPC RATING PREDICTOR</h1>
</header>
<button> GET STARTED</button>
</div>
);
}
export default Home;
If you are using react-router-dom#6 then there are a couple things you need to address.
The Switch component was replaced by the Routes component and all Route components must be wrapped/rendered directly by Routes, or another Route component in the case of nesting routes.
The Route component API changed; gone are the component, and render and children function props, all replaced by a single element prop taking a ReactNode, a.k.a. JSX, value.
Example:
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Home from './components/Home';
import Glazing from './components/Glazing';
import Navigation from './components/Navigation';
class App extends Component {
render() {
return (
<BrowserRouter>
<div>
<Navigation />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/glazing" element={<Glazing />} />
</Routes>
</div>
</BrowserRouter>
);
}
}
See the Upgrading from v5 guide for other changes.
I've been working on a react single page app and have been trying to get the routing to work.
I believe the routing itself actually works however the page does not load the correct content unless the page is manually reloaded. Back and forward browser arrows also work.
For example I can navigate to localhost:3000 fine and the content is loaded correctly but when I press a button to navigate to localhost:3000/contacts nothing is displayed unless I refresh the page. Once manually refreshed the contacts page shows up. What gives?
index.tsx
import React from 'react'
import ReactDOM from 'react-dom'
import { BrowserRouter as Router } from 'react-router-dom';
// Import App component
import App from './App'
// Import service workers
import * as serviceWorker from './serviceWorker'
// Render App component in the DOM
ReactDOM.render(
<Router>
<App />
</Router>
, document.getElementById('root')
)
serviceWorker.unregister()
App.tsx
// Import necessary dependencies
import React from 'react'
import Routes from './Routes'
// Create App component
function App() {
return (
<div className="App">
<Routes />
</div>
)
}
export default App
history.tsx
import { createBrowserHistory as history} from 'history';
export default history();
Home/Home.tsx
import React, { Component } from "react";
import history from './../history';
import "./Home.css";
export default class Home extends Component {
render() {
return (
<div className="Home">
hello home
<button onClick={() => history.push('/Contact')} value='click here'>Get Started</button>
</div>
);
}
}
Contact/Contact.tsx
import React, { Component } from 'react';
class Contact extends Component {
render() {
return (
<div>
hello world
</div>
);
}
}
export default Contact;
Routes.tsx
import React, { Component } from "react";
import {BrowserRouter, Router, Switch, Route } from "react-router-dom";
import Contact from "./Contact/Contact";
import Home from "./Home/Home"
import history from './history'
export default class Routes extends Component {
render() {
return (
<div>
<Router history={history}>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/Contact" component={Contact} />
</Switch>
</Router>
</div>
)
}
}
Any help greatly appreciated
I think there's some extra code that might be causing conflict. You're defining the Router from react-router-dom twice:
Once here, in index.tsx
ReactDOM.render(
<Router> // here
<App />
</Router>
, document.getElementById('root')
)
and then again in Routes.tsx
<Router history={history}> // here
<Switch>
<Route path="/" exact component={Home} />
<Route path="/Contact" component={Contact} />
</Switch>
</Router>
You have to drop one of them, they're probably conflicting each other
Update
In addition to that, I think you should not use the history object directly from your export, but access it through the HOC withRouter. Then, you'd wrap
So you'd do something like this
import React, { Component } from "react";
import { withRouter } from 'react-router-dom'
import "./Home.css";
class Home extends Component {
const { history } = this.props
render() {
return (
<div className="Home">
hello home
<button onClick={() => history.push('/Contact')} value='click here'>Get Started</button>
</div>
);
}
}
export default withRouter(Home)
I think the issue here is that you need to wrap your pages with withRouter() like so:
import React, { Component } from "react";
import history from './../history';
import "./Home.css";
import { withRouter } from 'react-router-dom'; //<---------- add this
class Home extends Component {
render() {
return (
<div className="Home">
hello home
<button onClick={() => history.push('/Contact')} value='click here'>Get Started</button>
</div>
);
}
}
default export withRouter(Home); //<-------------- and add this
You will need to do the same on your Contact page as well.
Why do you have two routers?
I guess you simply need to remove the Router either in index.tsx or in Routes.tsx
According to you file naming I would remove the Router in Routes.tsx
It seems like you are using the history package for navigation. If you are using the react-router v5, then you may have to downgrade the history package to 4.10.1 until the history package developers issue a new release with the fix. As of writing this, the latest release version of history package is v5.0.1, and if you see a new release than this, you can try with that version first to see if it works, before doing the downgrade to 4.10.1
Issue Link -> https://github.com/remix-run/history/issues/804
I'm working on a react app and I have several components I want to use on my root path. I wonder what are best practices as far as rendering then on one component and then linking that component to my root or if I could add all components to my root path.
I want to add 3 other components to root path.
This is my app.js file:
import React, { Component } from "react";
import { BrowserRouter, Route } from "react-router-dom";
import Header from "./components/Header";
import EyewearTitle from "./components/EyewearTitle";
import Buy from "./components/Buy";
import './App.css';
class App extends Component {
render() {
return (
<BrowserRouter>
<div>
<Header />
<Route exact path="/" component={EyewearTitle} />
<Route exact path="/buy" component={Buy} />
</div>
</BrowserRouter>
);
}
}
export default App;
You should add all components you want to render under a single component. For example, I might use a <ShoppingScreen/> component, and on that screen, would render:
render() {
return(
<div className="shopping-screen">
<ShoppingScreenSideBar/>
<ShoppingScreenItems/>
</div>
);
}
I am working on a simple demo React project. I have a Home component which gets rendered when directly placed in main.js but when placed inside the Router in Routes.js, it is not rendered. Can anyone let me know what am I doing wrong here?
main.js file
import React from "react";
import {render} from "react-dom";
import {App} from "./app/App";
import Routes from "./app/Routes";
render( <Routes />,
document.getElementById("root")
)
Routes.js file
import React from "react";
import {
BrowserRouter as Router,
Route,
Switch,
} from "react-router-dom";
import {App}
from "./App";
import Home from "./components/Home";
export default function Routes(props) {
console.log('Routes');
return (
<Router>
<App>
<Switch>
<Route path="/" exact component={Home} />
</Switch>
</App>
</Router>
)
}
App.js file
import React from "react";
import Header from "./components/Header";
export class App extends React.Component {
render() {
console.log("App render");
return (
<div>
<h1> Welcome to React </h1>
<Header/>
</div>
)
}
}
Header.js file
import React, {Component} from 'react';
import {NavLink} from 'react-router-dom';
export default class Header extends Component {
render() {
console.log("Header render");
return (
<div>
<NavLink to="/" exact>
Home
</NavLink>
</div>
)
}
}
Home.js file
import React, {Component} from "react";
export default class Home extends Component {
render() {
console.log("Home render");
return (
<div>
<h2>Hello World!</h2>
</div>
)
}
}
This is because you are using App component as the wrapper of whole app, and defined the Switch as the children of App component, so you need to use this.props.children inside App.
Like this:
export class App extends React.Component {
render() {
console.log("App render");
return (
<div>
<h1> Welcome to React </h1>
<Header/>
{this.props.children}
</div>
)
}
}
Consider this example to make the whole picture more clear, if you write:
<App>
<Home />
</App>
Means Home will get passed as children to App component, automatically it will not get rendered inside App, you need to put this.props.children somewhere inside App.
With react-router-v4 which you seem to be using, it is possible to have dynamic Routing which means you can add the Routes within nested components and hence apart from the solution that #MayankShukla suggested you could also keep the <Switch> and other routes within App like
export default function Routes(props) {
console.log('Routes');
return (
<Router>
<App/>
</Router>
)
}
export class App extends React.Component {
render() {
console.log("App render");
return (
<div>
<h1> Welcome to React </h1>
<Header/>
<Switch>
<Route path="/" exact component={Home} />
</Switch>
</div>
)
}
}
You could read more about the advantages of Dynamic Routing here
I am designing a website in which the header is the same for three pages.
By default the fist page should have the following components
Header QueryList
and on click of a button present in Header the QueryList component should change to FindExpert.js.
Along with the change in Page, the URL also changes on the click of a button.
Header FindExpert
Since header is present in both the screens and I don't want to call the component again and again in every js file.So, I used ternary operator in the header.js file so that I can route in half of the page.
App.js
import React, { Component } from 'react';
import {BrowserRouter,Route,Router,Switch} from 'react-router-dom';
import {Header} from './Header.js';
import {FindExpert} from './FindExpert.js';
class App extends Component {
render() {
return (
<div>
<BrowserRouter>
<Switch>
<Route exact path="/" component={Header} />
<Route path="/findexpert" component={FindExpert} />
</Switch>
</BrowserRouter>
</div>
);
}
}
export default App;
Header.js
import React, { Component } from 'react';
import {Constants} from './constants.js';
import {QueryList} from './QueryList.js';
import {FindExpert} from './FindExpert.js';
export class Header extends React.Component{
constructor(props) {
super(props);
this.state = {
ProfileData: {},
profileImage: "profile-pic.svg",
isClicked:false
};
this.findExpertClicked = this.findExpertClicked.bind(this);
this.findExpertPage=this.findExpertPage.bind(this)
}
findExpertClicked() {
console.log("Find expert clicked");
this.setState({
isClicked:true
})
}
findExpertPage(){
this.props.history.push('/findexpert');
}
render(){
return(
<div>
<div className="col-md-12 HeaderBar">
<div className="HeaderContent">
</div>
</div>
<div className="ProfileHeader">
<div className="profileImageDiv">
<img src={this.state.profileImage} className="profileImageSrc" alt="Alternate"></img>
</div>
</div>
<div className="headerButtons">
<div className="ExBtnDiv" onClick={this.findExpertClicked}><span className="ExBtn">Find Expert</span></div>
</div>
</div>
<div>{(this.state.isClicked===false)?<div><QueryList/></div> :<div>{this.findExpertPage()}</div>}</div>
</div>
)
}
}
And in FindExpert.js, suppose I have a simple Hello world.
import React, { Component } from 'react';
import {Header} from './Header.js';
import {Constants} from './constants.js';
export class FindExpert extends React.Component{
render(){
return(
<div>
Hello world
</div>
)
}
}
Through the above code, the QueryList comes below the Header as expected but when clicked on the find expert button, the whole page changes.
Since I don't want to call header.js in both the files, is there a way to keep the header constant and change the contents below it as well as change the url when find expert button is clicked.
You have to create separate components for Header and the content to be shown on the homepage. And directly render the Header component inside App.js
This way Header component will always be rendered and only the page content would change according to the current route.
For example:
import React, { Component } from 'react';
import {BrowserRouter,Route,Router,Switch} from 'react-router-dom';
import {Header} from './Header.js';
import HomePage from './HomePage.js';
import {FindExpert} from './FindExpert.js';
class App extends Component {
render() {
return (
<div>
<Header />
<BrowserRouter>
<Switch>
<Route exact path="/" component={HomePage} />
<Route path="/findexpert" component={FindExpert} />
</Switch>
</BrowserRouter>
</div>
);
}
}
export default App;