When a user goes to my domain www.example.com they see my webpage I created using React. I want to use React to show them a different webpage when they go to www.example.com/anotherpage instead.
This is the code I have in my index.js file which creates the webpage at www.example.com,
const element = <h1>Hello, world</h1>;
ReactDOM.render(element, document.getElementById('root'));
There are multiple solution for this, if you are creating an SPA with create-react-app, then one of the most popular solution is by using react-router.
As shown in the example, then the basic routing is like this:
import React from "react";
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
export default function App() {
return (
<Router>
<div>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/users">Users</Link>
</li>
</ul>
</nav>
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/users">
<Users />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</div>
</Router>
);
}
function Home() {
return <h2>Route Home</h2>;
}
function About() {
return <h2>Route About</h2>;
}
function Users() {
return <h2>Route Users</h2>;
}
However if you are using another framework such as Next.js, then they have the filesystem pages where creating a page under /pages/ folder will create a new route.
You need to use React Router for this purpose and declare separate routes for pages you want access to.
npm install react-router-dom
afterward, you can create separate components for the specific routes and attach them to the Routes as seen below,
import { BrowserRouter as Router,Route,Switch} from 'react-router-dom'
const Home = () => <h1>hello world!</h1>
const AnotherPage = () => <div>Another page!</div>
const App = () => {
<Router>
<Switch>
<Route path="/" component={Home}/>
<Route path="/anotherpage" component={AnotherPage}
</Switch>
</Router>
}
export default App;
You can look at the documentation for more examples react-router Quickstart
you should use npm install react-router-dom with nested routing for a better approach
Related
I know this question has been asked plenty of times. But sadly after implementing all of the possible solutions I still get a blank browser page after using Route, Routes.
My Code:
import { Container } from 'react-bootstrap'
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import Header from './components/Header'
import Footer from './components/Footer'
import HomeScreen from './screens/HomeScreen'
function App() {
return (
<Router>
<Routes>
<Header />
<main className="py-5">
<Container>
<Route path='/' component={<HomeScreen/>} />
</Container>
</main>
<Footer/>
</Routes>
</Router>
);
}
export default App;
Thank You for for help!
Issues
In react-router-dom#6 the Route components can only be rendered directly by the Routes component or another Route component in the case of route nesting.
The Route component API also changed significantly. There are no longer any component or render and children function props. They are replaced by a single element prop taking a React.ReactNode, a.k.a. JSX.
Solution
Move the Routes component down the tree to directly wrap the Route component(s), and switch to using the element prop to pass the routed content.
function App() {
return (
<Router>
<Header />
<main className="py-5">
<Container>
<Routes>
<Route path='/' element={<HomeScreen />} />
</Routes>
</Container>
</main>
<Footer/>
</Router>
);
}
I think you shouldn't nest elements other than <Route> inside <Routes> component. When location changes, <Routes> looks on all of his <Route> children and choose the one that fits. You nested your <Route> element inside <Header> so probably that's the problem. Try to rearrange the structure and move Routes to the top level.
I'm trying to display my 'Home' component in my React project via react-router-dom. Thought I got your tone done right, I don't have a compile time error but the Home component just doesn't show up. Do you have an idea ?
App.js :
import Navbar from "./Components/Navbar";
import {
BrowserRouter,
Routes,
Route
} from "react-router-dom";
import Home from "./Pages/Home";
function App() {
return (
<div className="App">
<BrowserRouter>
<Navbar />
<Routes>
<Route pathname="/" element={<Home />}> </Route>
</Routes>
</BrowserRouter>
</div>
);
}
export default App;
Home.js :
import React from "react";
import banner from "../assets/banner.jpg";
import {Link} from 'react-router-dom';
import '../Styles/Home.css';
function Home(){
return (
<div className="home" style={{ backgroundImage: `url(${banner})` }}>
<div className="headerContainer">
<h1>Food Corner</h1>
<p>AMERICAN FOOD AT A CLICK.</p>
<Link>
<button> Order Now </button>
</Link>
</div>
</div>
);
}
export default Home;
If this is Router Router v6 (assuming since you are using <Routes>...</Routes>), the prop name is "path" and not "pathname"
So this:
<Route pathname="/" element={<Home />}> </Route>
Should be this:
<Route path="/" element={<Home />}> </Route>
Here are the docs for React-Router-Dom v6 (which is different than the v5 docs): Here
You should also change your react-router-dom imports. You should import BrowserRouter as Router like:
import { BrowserRouter as Router } from 'react-router-dom'
You have a couple minor issues:
The Route component uses a path prop, not a pathname prop. With no path prop there is no matching path and Home is not rendered.
<Route path="/" element={<Home />} />
The Link is missing what it's linking to, i.e. it is missing the to prop. This causes a TypeError: Cannot read properties of undefined (reading 'pathname') error. Add the to prop link destination. Example:
<Link to="/order">
<button> Order Now </button>
</Link>
I am designing a web site using material-ui (https://material-ui.com/). I have toolbar with buttons. As usual, I want to navigate another html page when I click one of the buttons and render an initial component for new html page. For example, from 'Main Page' (for now, its localhost:3000/) to 'About' page (localhost:3000/About).
I tried something similar to this,
import { Link } from 'react-router-dom';
function ListItemLink(props) {
const { icon, primary, to } = props;
const CustomLink = props => <Link to={'/About'} {...props} />;
return (
<Button component={CustomLink} /> About
);
}
https://github.com/mui-org/material-ui/issues/10955 but it did not work. I searched many other methods but none of them is doing what I want. In the picture below, I have 'About' and 'News' folders under public folder. Each of them has its own index.html file. And I also have 'index.js' under src folder.
By default, nmp starts index.html under 'public' folder and execute index.js for this html file.
I want to make this scenario when I route other folders with button click.
Is there any preferrable way to do this ?
Thanks.
I recommend reading the documentation for React Router.
https://reactrouter.com/web/guides/quick-start
In the code below, the Switch component is what is used to see what should be rendered based on the Route components under it.
You need this switch logic setup or your buttons won't do anything.
import React from "react";
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
export default function App() {
return (
<Router>
<div>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/users">Users</Link>
</li>
</ul>
</nav>
{/* A <Switch> looks through its children <Route>s and
renders the first one that matches the current URL. */}
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/users">
<Users />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</div>
</Router>
);
}
My Navigation component code
import { BrowserRouter as Router, Link } from "react-router-dom";
<Router>
<header>
<ul className="social">
{/* Couldn't figure this out */}
{/* Link doesn't route properly but a href does */}
<li>
<Link to="/">
!Home
</Link>
</li>
<li>
Home
</li>
</header>
</Router>
Tag works for loading the webpage but tag doesnt work.
The class where I have defined my HashRouter and Switch.
When invoking " !Home " it doesn't load and nor outputs anything in the chrome/firefox console but this same link in href "Home" works and loads the page.
<HashRouter>
<Switch>
<Route
exact
path="/"
render={props => <Posts postsObj={this.state.blog} />}
/>
<Route
path="/post1"
render={props => <Post postObj={this.state.blog[0]} />}
/>
<Route
path="/post2"
render={props => <Post postObj={this.state.blog[1]} />}
/>
<Route
path="/post3"
render={props => <Post postObj={this.state.blog[2]} />}
/>
</Switch>
</HashRouter>
Calling "Main.jsx" from "MainApp.jsx"
<div>
<Header />
<section>
<Main /> // Calling function here.
<Nav />
</section>
<Social />
<Footer />
</div>
Github Source code : https://github.com/SensehacK/react-app
Thanks.
You have two parallel Routers (HashRouter is a special kind of Router component) in your project, one in the Header component and another in Main. Having multiple routers is confusing and could easily break routing, which is probably why your Link is not working as expected.
Since the HashRouter seems to be the one that's expected to work, you might want to move it to the top level, for example to the MainApp component and remove the other. Make sure whenever you use Link, it is nested in a Router (or HashRouter in your case) through its parents/ancestors.
Turns out I got confused between HashRouter and BrowserRouter.
I followed HashRouter in the main component and use
<Main Component>
<HashRouter> <Switch>
<Route exact path="/" render= {component_name1} />
</Switch> </HashRouter>
</Main Component>
And when I was trying to link the path "/" in different component towards "component_name1"
I was using <Link to="/" > Go Home </Link> ( BrowserRouter ) in my HashRouter routing definition.
So for HashRouter to work I need to use <NavLink to="/">Go Home</NavLink>
I was following 2 different sources and hastily forgot about differences of HashRouter and BrowserRouter by even their names and implementation.
Sometimes deadlines takes the best of you to even spot the basic stuff.
Thanks for the response though #Claire Lin
Github code fix commit
I'm stuck creating a single page app using react, redux, react-router and react-redux-router bindings.
The route http://localhost:3001/register is simply not matched by the router and Cannot GET /register is returned to the browser because the server obviously doesn't know the route. I'm relatively new to the react-redux stack and may be missing something pretty basic.
Edit: The IndexRoute is working and is displaying the Home-Component inside the App-Compontent.
Edit2: I'm not using server side rendering and am developing using the webpack-dev-server.
But here are the related code-snippets so far:
entry.js
const store = createStore(
reducer, //from reducers.js
applyMiddleware(routerMiddleware(browserHistory))
);
const history = syncHistoryWithStore(browserHistory, store);
render(
<Provider store={store}>
<Router history={history} routes={routes} /> //routes from routes.js
</Provider>,
document.getElementById('app')
);
reducers.js
const rootReducer = combineReducers({
RegisterForm,
routing: routerReducer //provided by react-router-redux
});
export default rootReducer;
routes.js
const routes = (
<Route path='/' component={App}>
<IndexRoute component={Home} />
<Route name='register' path='register' component={RegisterForm} />
</Route>
);
export default routes;
Navigation.jsx (rendered inside App.jsx)
import React from 'react';
import {Link} from 'react-router';
export default class Navigation extends React.Component {
render() {
return (
<div className="mdl-layout mdl-js-layout mdl-layout--fixed-header">
<header className="mdl-layout__header">
<div className="mdl-layout__header-row">
<span className="mdl-layout-title">there!</span>
<div className="mdl-layout-spacer"></div>
<nav className="mdl-navigation mdl-layout--large-screen-only">
<Link className="mdl-navigation__link" to="/">Home</Link>
<Link className="mdl-navigation__link" to="register">Register</Link>
</nav>
</div>
</header>
<div className="mdl-layout__drawer">
<span className="mdl-layout-title">there!</span>
<nav className="mdl-navigation">
<Link className="mdl-navigation__link" to="/">Home</Link>
<Link className="mdl-navigation__link" to="register">Register</Link>
</nav>
</div>
<main className="mdl-layout__content">
<div className="page-content">
{this.props.children}
</div>
</main>
</div>
);
}
}
Maybe it is obvious to someone, what I am missing here. If you need more of the code please let me know.
As you say, the problem is that your backend does not know how to handle requests to /register. The solution is to tell your backend to return the react application (same as requests to /) on such requests.
If you are developing with pure webpack-dev-server I'm not 100% sure what's the best way to do this, but you can take a look at the answer here which will probably work: Stating directive templateUrl relative to root
You can use hashHistory instead of browserHistory. It's written in react-router's documentation.
Of course, you will need to configure the Link's to props so it will redirect properly according to the needs of hashHistory. Later on, when you are back using browserHistory, you need to reconfigure those links again.