New to react and working with React Router so that I have many pages.
I am in my Home.jsx and it looks like this.
import React, { Component } from 'react';
import randomimage from '../imagefolder/rentalbackground.jpg';
import Header from './Header';
import Footer from './Footer';
import Rentals from './Rentals';
import {
BrowserRouter as Router,
Route,
Redirect,
Link
} from 'react-router-dom';
class Home extends Component {
render() {
return (
<div>
<Header />
<Router>
<div>
<Link to="/rentals">Rentals</Link>
<main>
<Route path="/" component={Rentals} />
</main>
</div>
</Router>
<p>some paragraph here</p>
<img src={randomimage} alt="imagerand" />
<Footer />
</div>
);
}
}
export default Home;
And my Rentals component looks like this.
import React, { Component } from 'react';
class Rentals extends Component {
render() {
return (
<div>
<p>this is for all the rentals</p>
</div>
)
}
}
export default Rentals;
What I am trying to do is create a page called localhost:3000/rentals which only displays the paragraph from the "Rentals" component in a new page. But when I click on the rentals link, which is on the Home.jsx, it displays all the components from the "Home" component including the picture, and the Header and the Footer components too.
I tried using exact path on the Route and nothing happens. How might I achieve this?
This is because you have placed your Router component inside your Home component which in turn have your Header and Footer. So all child components will be rendered inside your Home component.
Your router component should be on the top level of your App and all other components like Home, Rentals etc should be added as a child to the router.
Just to give you an example, it should be something like this.
//Your app initialisation, Top Level
ReactDOM.render(
<div style={{height: '100%'}}>
//All Your routes can be exported at one place and passed to your router as props. This will also help you maintain routes at one place
<Router history={browserHistory} children={routes}/>
</div>,
document.getElementById('root')
)
Will suggest you to read more about using React router and best practices since this is an architecture problem and quite broad topic to be answered here.
Related
I've read some answers here and it seems they are all replying to a specific problem. Mine more about usage and placement rather than a problem I am facing. I also read the documentation but it does not answer my question.
My question is where to use react-router components?
Do I import (and use) BrowserRouter in index.js or App.js or does it go wherever the navigation bar is?
Do Route, Switch, NavLink, Link must be in the same module/file? If not, do I use them around the navigation bar element?
On the official website it shows that <Switch> is INCLUDED within <BrowserRouter> tags AFTER <Link> elements were used. Can I conclude from that <Switch> always come in the same element where <Link> elements were used?
I am beyond confused as to where these tags should be used in relation to other tags - not how to get them to work.
Finally, if I have a react app where index.js renders App.js. App.js is like a table of content of the main components I am rendering. Let's say: Header, Main, Footer. Inside the Header there are Greeting and then a NavigationBar. I want my links to be in the NavigationBar component as menu items. Where do I implement react-router components?
Thank you very much in advance.
1 . You can import and use BrowserRouter either in the root of the project which is index.js or in app.js just make sure it wraps around the Switch and Routes .
2 . The Switch Component must wrap all the Route components so this format is the most common way of using it :
<Switch>
<Route exact component={<Component />} path="/" />
</Switch>
You can use NavLink or Link almost anywhere in your components which are imported in Route component prop .
NavLink and Link is just for navigating between Routes in your app .
And for the last part you can have a Layout.js component to have Header Main and Footer components inside of it wrap all the other components which are used in Routes for example :
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
// Router
import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>
,
document.getElementById('root')
);
App.js
import React from "react";
// Router
import { Switch, Route, withRouter } from "react-router-dom";
// Components
import Home from "./routes/Home/Home";
function App() {
return (
<Switch>
<Route exact component={Home} path="/" />
</Switch>
);
}
export default App;
Home.js
import React from "react";
// Router
import { NavLink } from "react-router-dom";
// Components
import Layout from "../../components/Layout/Layout";
function Home(props) {
return (
<Layout title="Homepage">
<NavLink to="/ss">ss</NavLink>
<NavLink to="/">/</NavLink>
</Layout>
);
}
export default Home;
Define Header Footer and Main in Layout.js :
Layout.js
import React, { Fragment } from "react";
import { Helmet } from "react-helmet";
// Components
import Header from "../Header/Header";
import Footer from "../Footer/Footer";
function Layout({ title, children }) {
return (
<Fragment>
<Helmet>
<title>
{title}
</title>
</Helmet>
<Header />
{children}
<Footer />
</Fragment>
);
}
export default Layout;
The children prop is basically the Home.js component which has Layout wrapper so the Home.js component will display Header Footer from layout and it's own content .
This is the most common way of using the react-router-dom in a react project .
Note
The Switch component will only render the first route that matches/includes the path. Once it finds the first route that matches the path, it will not look for any other matches. Not only that, it allows for nested routes to work properly, which is something that Router will not be able to handle.
Fragment is just for wrapping the component tags like this :
import React , { Fragment } from 'react';
function Component() {
return (
<Fragment>
<Other />
<Main />
</Fragment>
);
}
If you delete Fragment it will throw an error you can read more about Fragments here .
I'm writing my first React app, in Typescript.
Following a tutorial, I've created a single <Link> that references a single <Route> all inside my <Router> component. When I click the Link in my browser, the URL changes, but the Route does not render. I cannot figure out why the Route does not render. I've read a bunch of SO questions, but they're all related to advanced uses of Router; I can't get the most basic usecase to work.
Here's my top-level component:
import React, {Component} from 'react';
import {BrowserRouter as Router, Route, Link} from "react-router-dom";
import {StaticComponent} from "./StaticComponent/StaticComponent";
export default class App extends Component{
render() {
return (
<div className="App">
<Router>
<header className="App-header">
<span>header</span>
<Link to="/staticComponent">Static Component</Link>
</header>
<main>
<span>body</span>
<Route path="/staticComponent" element={StaticComponent}/>
</main>
</Router>
</div>
);
};
}
Here's StaticComponent:
import React from 'react';
import { BrowserRouter as Router } from 'react-router-dom'
export function StaticComponent () {
return (
<h2>You are at Static Component</h2>
);
};
As you can see, top-level component displays as you'd expect:
But when I click the link, the StaticComponent does not display:
Is there some small detail I'm getting wrong here? Thanks!
I never figured out how to use the "element" attribute on the <Route> element, nor the "component" attribute that #gbalduzzi mentioned. However, implementing App.tsx in the following way does work:
import React, {Component} from 'react';
import {BrowserRouter as Router, Route, Link} from 'react-router-dom';
import {StaticComponent} from "./StaticComponent/StaticComponent";
export default class App extends Component<{}, {}>{
render() {
return (
<div className="App">
<Router>
<header className="App-header">
<span>header</span>
<Link to="/staticComponent">Static Component</Link>
</header>
<main>
<span>body</span>
<Route path="/staticComponent">
<StaticComponent />
</Route>
</main>
</Router>
</div>
);
};
}
Also, line 2 of StaticComponent.tsx seems to have been unnecessary; I have since taken it out.
Finally, make sure you're using the correct version of React Router. The JSX files that work for React Router 5 do not seem to work for React Router 6.
I am currently learning React and I am trying to create a simple modal that will display when the page loads. When I saved the changes, the page went to white and there aren't any errors in the console. I set the state to true and then tried calling it up in the render, thinking that this could be a way to do it. Can someone tell me what is it that I am doing wrong?
Modal.js
import React from 'react';
class Modal extends React.Component{
constructor(props){
super(props)
this.state = {open:true}
}
render(){
return (
<div open={this.state.open}>
<p>Hello</p>
</div>
)
}
}
export default Modal;
How I imported it into my app.js file
import React from 'react';
import HomePage from './components/HomePage'
import DadJokesApi from './components/DadJokesApi'
import SportsJokesApi from './components/SportsJokesApi'
import ProgrammingJokesApi from './components/ProgrammingJokesApi';
import { Route, Switch} from "react-router-dom";
import Modal from './components/Modal';
function App() {
return (
<main>
<Modal />
<Switch>
<Route path="/DadJokes" component={DadJokesApi} />
<Route path="/SportsJokes" component={SportsJokesApi} />
<Route path="/ProgrammingJokes" component={ProgrammingJokesApi} />
<Route path="/" component={HomePage} />
</Switch>
</main>
);
}
export default App;
Try to fix few issues in your code:
you are missing wrap your Routes with Router
the div has open prop which is not required
I have taken your code and made it work basic way. Go thru it and leave a comment for further doubts and I will edit my answer.
https://codesandbox.io/s/fragrant-frost-1hj6r?file=/src/App.js
Also, in your case, try to to maintain a state called open in your parent (eg: App.js) and pass it to your Modal component. In your app.js you can decide and turn the state open to off/on based on your loading condition.
I've searched existing solutions on here but nothing seems to answer my question, so here is my issue.
I've set up a new Laravel project using react, and have just put together a basic Dashboard page, which currently is just meant to render a component called PageHeader with the title 'Dashboard' on it. However, the div is not being populated by this content.
Here is my setup:
app.js (using react-router 3.2.0):
require('./bootstrap');
import React from 'react';
import { render } from 'react-dom';
import { hashHistory, Router, Route } from 'react-router';
import Dashboard from './components/Dashboard';
render((
<Router history={hashHistory}>
<Route path="/home" component={Dashboard} />
</Router>
), document.getElementById('app')
);
The component Dashboard:
import React, { Component } from 'react';
import PageHeader from './../PageHeader';
export default class Dashboard extends Component {
render() {
return (
<div>
<div>
<PageHeader title="Dashboard" />
</div>
</div>
);
}
}
The component PageHeader:
import React, { Component } from 'react';
export default class PageHeader extends Component {
render() {
const { title } = this.props;
return (
<div className="row">
<div className="col-sm-12">
<h1>{ title }</h1>
</div>
</div>
);
}
}
My web.php file (I basically just use a wildcard as I am using the same blade file to render all pages):
Auth::routes();
Route::group(['middleware' => ['auth']], function() {
Route::get('/{any}', function () {
return view('page');
})->where('any', '.*');
});
The blade file rendering the main content:
#extends('layouts.app')
#section('content')
<div class="container">
#if (session('status'))
<div class="alert alert-success" role="alert">
{{ session('status') }}
</div>
#endif
<div id="app"></div>
</div>
#endsection
When I load the page, it throws no errors, but the app div element is always blank - I am wondering if it is because the page is loading too late for the actual content to render in?
I'm unsure why this is happening as I have recently finished a project very similar to this with the same components and modules, with no problems - so if anyone can shed some light on this I'd be grateful.
EDIT:
I am using webpack mix to transpile my css / js by the way if this helps.
I just had a very similar problem and the hangup was something to do with my react router setup. Try consolidating your "menu html" so that it is in the same render call as your initial react router setup.
Something like this. (not 100% sure here because I was using react router 4)
require('./bootstrap');
import React from 'react';
import { render } from 'react-dom';
import { hashHistory, Router, Route, Link } from 'react-router';
import Dashboard from './components/Dashboard';
render((
<Router history={hashHistory}>
<div>
<div>
<Link to='/home'>Dashboard</Link>
</div>
</div>
<Route path="/home" component={Dashboard} />
</Router>
), document.getElementById('app')
);
Then modify your dashboard so that it just loads the props.children into that div
import React, { Component } from 'react';
export default class Dashboard extends Component {
render() {
return (
<div>
<div>
{this.props.children}
</div>
</div>
);
}
}
Again sorry for not running the code myself but I didn't want to switch around to react router 3. Bottom line is try to load your "menu html code" along with your initial react router render and also tie all your sub components somehow into that app.js. If youre still having trouble after that get rid of your react router code and just load a basic text react module to troubleshoot it down to your react router code.
I have made 3 components
1)Navbar
2)Content
3)Pagination
On home page I want to display all 3 components.
I have made another component Matchinfo which should get displayed when we click on view stats button (see screenshot for more clarification) .
In app.js how should I make use of Routes so that 3 components will get display on home page i.e localhost:3000/ and when I click on view stats button it should render component Matchinfo.
In app.js :
import React, { Component } from 'react';
import { Route, NavLink, HashRouter } from "react-router-dom";
import './App.css';
import Navbar from './components/navbar';
import Content from './components/content';
import Pagination from './components/pagination';
import Matchinfo from './components/matchinfo';
class App extends Component {
render() {
return (
<div className="App">
<div className="content">
<Route path="/" component={Navbar, Content, Pagination}/>
<Route path="/match" component={Matchinfo}/>
</div>
</div>
);
}
}
export default App;
You no need to call these components in app.js using routes. I would request you to create sepearte component like Home(see example below home.js).
Then, In app.js call Home component
import Home from './components/home';
<Route path="/" component={Home}/>
create home.js under components
Call Navbar, Content annd Pagination components in Home component
import React, {Component} from "react";
import Navbar from './components/navbar';
import Content from './components/content';
import Pagination from './components/pagination';
class Home extends Component {
constructor(props) {
super(props);
this.state = {
}
}
componentWillMount() {
}
render() {
return (
<div>
<Navbar/>
<Content />
<Pagination/>
</div>
)
}
}
export default Home;
Since you want to display Navbar, Content annd Pagination components in home page so do it like above way. Here Home is your parent component and Navbar, Content annd Pagination are child components to Home.
One route is enough mostly for one web page and in React most of times you will play with child components. You no need to configure all the components with routes.
There are several ways achieving the result.
The first one is using render method for home Route. Also, use exact attribute of Route to ensure the location is matched exactly.
import React, { Component } from 'react';
import { Route, NavLink, HashRouter } from "react-router-dom";
import './App.css';
import Navbar from './components/navbar';
import Content from './components/content';
import Pagination from './components/pagination';
import Matchinfo from './components/matchinfo';
class App extends Component {
render() {
return (
<div className="App">
<div className="content">
<Route path="/" render={(props) => (
<React.Fragment>
<Navbar/>
<Content />
<Pagination/>
<React.Fragment/>
)} exact/>
<Route path="/match" component={Matchinfo} exact/>
</div>
</div>
);
}
}
export default App;
The second one, create auxiliary component Home, for example, and include it in your route, like this:
<Route path="/" component={Home} exact/>