Make multiple pages in ReactJS without using react-dom-router - javascript

I am a beginner in ReactJS web development and I wanted to ask, how can I make multiple pages in ReactJS (for example if I click on a button called "About me" that it will redirect to a different part of the whole site, for example example.com/aboutme) without using react-dom-router?
I don't want to change much in the codes because I already use my App.js as the main page.

You should use your own router with react-router-dom to do this. I preferably use HashRouter.
(What is the difference between HashRouter and BrowserRouter in React?)
Here is a simple example for routing in App.js;
import { HashRouter as Router, Route, Switch } from 'react-router-dom';
// Components
import Homepage from './components/Homepage';
import AboutMe from './components/AboutMe';
import Error404 from './components/Error404';
export default function App() {
return (
<Router>
<Switch>
<Route key="homepage" exact path={['/', '/homepage']}>
<Homepage />
</Route>
<Route key="aboutme" exact path="/aboutme">
<AboutMe />
</Route>
<Route path="*">
<Error404 />
</Route>
</Switch>
</Router>
);
}
After that when you go /aboutme you will see AboutMe component or when you go / or /homepage you will see Homepage component. If you try to go /blabla like this you will see Error404 component.

For example in your render:
<div>
<ul>
<li onClick={this.onItemClick}>About me</li>
</ul>
</div>
Function that starts on click:
onItemClick: function () {
this.props.history.push("/about-me");
}

Related

Why do I run into a blank page whenever I use react router , no matter what the version or use? [duplicate]

This question already has answers here:
React App goes blank after importing React-Router-Dom
(3 answers)
Closed 6 months ago.
I have tried many versions of RouterDOM and all I get when I use it is a blank page. This is just one example which I included BrowserReact in index.js. Still a blank page.
Can someone please help?
import logo from "./logo.svg";
import "./App.css";
import About from "./About";
import Home from "./Home";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
function App() {
return (
<div className="App">
<Routes>
<Route path="/" element={Home}>
This is in home
</Route>
</Routes>
</div>
);
}
export default App
Have you tried wrapping your component in tags?
The React Router documentation says you should use your component as JSX.
Like so:
<Routes>
<Route path="/" element={<Home/>} />
</Routes>

How to Embed a p5js Sketch in a React Project Using react-script-tag and react-router-dom?

I am trying to embed a p5js sketch in a React project. I am using react-script-tag to embed the .js file which contains the p5js sketch and I am using react-router-dom to manage the routes to the webpages. I have managed to get the p5js sketch displaying properly, however I am facing the following issue:
The ScriptTag referencing the p5js sketch is located within within the Route to '/p5js'.
<Route path="/p5js" element={<p5js />}/>
The p5js sketch only loads after I've refreshed the browser on that page, 'localhost:3000/p5js'. Once it loads, it remains on the screen even after I go to back to another page, say
<Route path="/home" element={<Home />}/>
How I can have the p5js sketch appear automatically when navigating to the p5js page? And how can I have the sketch disappear when navigating to new pages, such as the 'Home' page?
Here is my code:
App.js
import { BrowserRouter, Routes, Route } from "react-router-dom";
import "./App.css";
import Navbar from "./components/Navbar";
import Home from "./pages/Home";
import SQL from "./pages/SQL";
import SuperCollider from "./pages/SuperCollider";
import p5js from "./pages/p5js";
function App() {
return (
<>
<BrowserRouter>
<Navbar />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/sql" element={<SQL />} />
<Route path="/sc" element={<SuperCollider />} />
<Route path="/p5js" element={<p5js />} />
</Routes>
</BrowserRouter>
</>
);
};
export default App;
p5js.js
import React from 'react';
import ScriptTag from 'react-script-tag';
const p5js = () =>{
return (
<div className="p5js">
<ScriptTag type="text/javascript" src="sketch2.js" />
</div>
);
}
export default p5js;
I use react-p5-wrapper to use p5 as a component and have had similar issues with the p5 instance hanging around, consuming touch events and such.
I've found it useful to use p5's remove() function. Listen for a location change then call remove as needed.
Haven't had any issue with p5 not appearing / running when it's wrapper component is rendered.

Issue with react-router-dom and github pages

So, first I had an issue with the routes not working, but I resolved that with react-router-dom's "baseline" property, but now despite the home page loading, the subsequent links render beneath the first component, which is supposed to dissapear entirely when the link is clicked.
It works fine locally.
This is my app.js
import React from 'react';
import './App.css';
import Navbar from './Component/Navbar/Navbar';
import RecipeList from './Component/RecipeList/RecipeList';
import { Switch, Route, BrowserRouter } from 'react-router-dom'
import RecipeItemDetails from './Component/RecipeItemDetails/RecipeItemDetails';
function App() {
return (
<BrowserRouter basename={process.env.PUBLIC_URL}>
<div className="App">
<Navbar/>
<Route exact path="/" component={RecipeList} />
<Route path="/recipes/:id" component={RecipeItemDetails} />
</div>
</BrowserRouter>
);
}
export default App;
any ideas? I've tried adding "exact" to the second route which didnt work, and I've also tried wrapping the router in a "switch", but that doesnt work either. I'm stumped.
your routes are inside el. so the the re rendered part when the route change is the Route components , and the div and navbar not re-rendered this is the reason you see the new routes beneath the first component, you should do something like this
<BrowserRouter basename={process.env.PUBLIC_URL}>
<Route exact path="/" component={RecipeList} />
<Route path="/recipes/:id" component={RecipeItemDetails} />
</BrowserRouter>
and then in the RecipeList and RecipeItemDetails import the Navbar and enclose it in the desired

React Router v4 Multiple Dynamic Routes

I'm new to React Router so if this has been asked before maybe someone could point me in the right direction! Basically I have a WordPress install that I'm pulling in my websites data from through the API.
I've created custom routes to query my pages and my posts by slug.
Using react router I was able to create a template called Page.js which changes dynamically using the code below.
However, now I'm trying to do the same exact thing with the blog posts but the app isn't using Blog.js its still defaulting back to Page.js
here's my App.js code...
import React from "react";
import { BrowserRouter as Router, Route } from "react-router-dom";
import Home from './pages/Home';
import Page from './pages/Page';
import Blog from './pages/Blog';
import Header from './components/Header';
import Footer from './components/Footer';
class App extends React.Component {
render() {
return (
<Router>
<div>
<Header/>
<Route exact path="/" component={Home} />
<Route path="/:slug" component={Page} />
<Route path="/blog/:slug" component={Blog} />
<Footer/>
</div>
</Router>
);
}
}
export default App;
More Details:
Page.js works by checking const { slug } = this.props.match.params; and then querying WordPress using that slug to pull in the data it needs. In componentDidUpdate i'm checking prevProps to see if the slug matches the previous slug, if not it fetching the new data.
This works great and I was hoping to do the same in the Blog.js as well.
However, if this isn't the best approach please advise another method.
Two things:
Use element: This will allow only one route to be used, no composing. (See this documentation)
Check the order of path statements: Use defined paths before :param, this avoids considering /blog/:slug as a /:slug parameter.
`
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
class App extends React.Component {
render() {
return (
<Router>
<div>
<Header/>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/blog/:slug" component={Blog} />
<Route path="/:slug" component={Page} />
</Switch>
<Footer/>
</div>
</Router>
);
}
}
I think you're pretty close to the recommended implementation, just a few small tweaks should get you there.
First,
In your App.js file you're actually handling routing, without using the <Switch> component provided by React Router, replacing the <div> and </div> tags in your App.js file with <Switch> and </Switch> respectively should get this working for you. See below...
import React from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom"; //make sure you import it also!
import Home from './pages/Home';
import Page from './pages/Page';
import Blog from './pages/Blog';
import Header from './components/Header';
import Footer from './components/Footer';
class App extends React.Component {
render() {
return (
<Router>
<Switch> //Add this in
<Header />
<Route exact path="/" component={Home} />
<Route path="/blog/:slug" component={Blog} />
<Route path="/:slug" component={Page} />
<Footer />
</Switch> //Add this in
</Router>
);
}
}
export default App;
I would recommend going further though!
To make these components more understandable, you should refactor routing functionality into a routes.js file, and top-level App component logic/structure into the App.js file. See below...
In App.js:
This file is where you should handle your base application structure and logic. For example this file is where you'll import your <Header>, your <Footer>, and where the Route component will render.
import * as React from 'react'
import Header from './../Header/Header.jsx'
import Footer from './../Footer/Footer.jsx'
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
// Handle your top-level application state here
}
}
// define your top-level application functions here
render() {
return (
<div>
<Header />
<main>
{this.props.children} //This where the Route components will render
</main>
<Footer />
</div>
)
}
}
export default App
In Routes.js:
This file is where you should import your App component, and then handle the routing statements.
import React from 'react'
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
import App from './components/App'
import Home from './pages/Home'
import Page from './pages/Page'
import Blog from './pages/Blog'
/* construct routes */
export default () => {
return (
<Router>
<App>
<Switch>
<Route path='/' exact component={Home} />
<Route path='/blog/:slug' component={Blog} />
<Route path='/:slug' component={Page} />
</Switch>
</App>
</Router>
)
}
If you structure your application this way, your routing logic and top-level application logic are separate, and in the end your files will be less cluttered as both Route files and top-level App files can get fairly dense.
Hope this helps! Let me know if I can explain anything further.

issue with react-router showing component when not in route

I am using react-router and having some difficulties with it's behaviour.
The Nav shows on all pages as desired. However, the Profile shows on all pages too. I only want to show this on /home and also on the /music and /players pages, which it does. However, it also shows on the /charts page which is confusing me.
My code looks like the following.
import React from 'react';
import { Route } from 'react-router-dom'
import Nav from './components/Nav'
import Profile from './components/Profile'
import Players from './components/Players'
import Music from './components/Music'
import Charts from './components/Charts'
const App = () => {
return (
<section>
<Nav />
<Route path="/home">
<div>
<Profile avatarUrl={ avatarUrl }/>
<Route path="/players" component={Players}/>
<Route path="/music" component={Music}/>
</div>
</Route>
<Route path="/charts" component={Charts}/>
</section>
)
}
export default App;
I have read through the docs, tried putting in a Switch component, added exact to the home route but this leads to other unexpected behaviour.
Can anyone advise what I am doing wrong?
Thanks Pete!
Try this:
import React from 'react';
import { Route, BrowserRouter as Router } from 'react-router-dom'
import Nav from './components/Nav'
import Profile from './components/Profile'
import Players from './components/Players'
import Music from './components/Music'
import Charts from './components/Charts'
const Home = ({match}) => {
return (
<div>
<Profile avatarUrl={ avatarUrl }/>
<Route path=`${match.url}/players` component={Players}/>
<Route path=`${match.url}/music` component={Music}/>
</div>
);
};
const App = () => {
return (
<section>
<Nav />
<Router>
<Switch>
<Route path="/charts" exact={true} component={Charts}/>
<Route path="/home" component={Home} />
</Switch>
</Router>
</section>
)
}
export default App;
I haven't tested this, but this should work.
Assuming that you're using react-router v4, I don't know if you can actually use your home route in the way you've used it.
In the code above, Switch basically renders the first match between the routes specified under it. The exact keyword will ensure that only /charts path will display the Charts component.
The Home component will render in any path that starts with /home.
Now, for path /home/players, you'll see the Profile and the Players component, whereas for path /home/music, you'll see the other combination.
Hope this helps. :)
Edit:
Added Router to the code.
Edit:
Working code available here: https://codesandbox.io/s/8x9pql9m19
Change route on right hand side to:
/home
/home/players
/home/music
/charts

Categories