Before I begin I have been on the https://reacttraining.com/react-router/web/guides/quick-start to grasp the idea of how the react router works. I have created a simple 3 page site in react and I want to create a list which will allow me to show some nested components. Whilst the examples on reacttraining.com nicely work on in a singles js file. I have my site split over 3 js files:
APP.JS
import React, {Component} from 'react';
import {
BrowserRouter as Router,
Route,
Link
} from 'react-router-dom';
import {Home} from './Home';
import {User} from './User';
import {Artwork} from './artwork'
import {Header} from './header';
class App extends Component {
render(){
return (
<Router>
<div className="container">
<div className="row">
<div className="col-xs-10 col-xs-offset-1">
<Header />
</div>
</div>
<hr/>
<div className="row">
<div className="col-xs-10 col-xs-offset-1">
<Route path="/" exact component={Home}/>
<Route path="/home" exact component={Home}/>
<Route path="/user" component={User}/>
</div>
</div>
</div>
</Router>
);
}
}
export default App;
USER.JS Edited on 28/03/2017
import React, {Component} from 'react';
import {Artwork} from './artwork';
import {Route, Link} from 'react-router-dom';
export class User extends Component {
render() {
return (
<div className="row">
<div className="col-md-4">
<h3>The User Page</h3>
<p>User ID:</p>
<li><Link to="/user/artwork">Artwork</Link></li>
</div>
<div className="col-md-8">
<Route path="/user/artwork" component={Artwork}/>
</div>
</div>
);
}
}
export default User;
ARTWORK.JS
import React, {Component} from 'react';
export class Art extends Component {
render(){
return (
<div>
<h3>Art</h3>
</div>
);
}
}
export default Art;
The issue that I am having is that whilst i can navigate through to my top level menu items (Home and User) I can not access the artwork component on the the user page. when the artwork button is pressed my user component is removed.
If you're looking at the basic example on react-training, you'll notice that the "child" Route in the Topics component has ${match.url}/:topicId as the path:
<Route path={`${match.url}/:topicId`} component={Topic}/>
This is basically turning it into topics/:topicId which is needed because the top most component wouldn't know what to do with just :topicId.
Likewise, in your situation, your App.js doesn't know what to do with /artwork so it doesn't render anything. If you change your Route path and Link to in User.js to /user/artwork it should start working as desired.
To make your User component more composable/reusable, you'd want to do the same thing as react training and use the passed in match.url on the props.
Related
I'm having a problem with react-route. The NoteList component is not rendering.
app.js
import { BrowserRouter as Router, Routes } from 'react-router-dom';
import logoNotes from './img/logoNotes.png';
import NoteList from './components/NoteList/NoteList';
import './App.css';
function App() {
return (
<Router>
<div className='aplication-notes'>
<div className='notes-logo-container'>
<img src={logoNotes} className='notes-logo' alt='logo' />
</div>
<div className='note-list'>
<h1> my notes</h1>
<br></br>
<Routes
path='/src/components/NoteList/NoteList'
element={<NoteList />}
/>
</div>
</div>
</Router>
);
}
export default App;
I can see the div and h1 that is in the app.js file but not the Notelist component.
How can I solve this problem?
The Routes component is only responsible for wrapping Route components and handles the path matching duties. It doesn't take path or element props. These belong to the Route component.
Import the Route component and render the NoteList component by the Route and wrap the Route with Routes.
Example:
import {
BrowserRouter as Router,
Routes
Route // <-- import
} from 'react-router-dom';
import logoNotes from './img/logoNotes.png';
import NoteList from './components/NoteList/NoteList';
import './App.css';
function App() {
return (
<Router>
<div className='aplication-notes'>
<div className='notes-logo-container'>
<img src={logoNotes} className='notes-logo' alt='logo' />
</div>
<div className='note-list'>
<h1> my notes</h1>
<br />
<Routes> // <-- wrap Route components
<Route // <-- Route renders content
path="/src/components/NoteList/NoteList"
element={<NoteList />}
/>
</Routes>
</div>
</div>
</Router>
);
}
export default App;
Now when you navigate to "/src/components/NoteList/NoteList" in the browser you should see the UI rendered as well as the NoteList component.
I want to route specific component in other component but when I click on the link other components are disappeared
import React from 'react';
import { Route, Switch, BrowserRouter } from 'react-router-dom';
import Sidebar from '../componants/Sidebar'
import Navbar from '../componants/Navbar';
import Router from '../Routers/Routers'
import Answer from './Answer';
import Feed from './Feed'
const Layuot = () => {
return (
<>
<div className="container-fluid">
<Navbar />
<div className="rows row">
<div className='col-3'>
<Sidebar/>
</div>
<div className="col-9 ">
<div className="content">
<Switch>
<Route path='/feed'><Feed/></Route>
<Route path = '/answer/:q_id'><Answer/></Route>
</Switch>
</div>
</div>
</div>
</div>
</>
)
}
export default Layuot;
see output
enter image description here
See Url
enter image description here
Every component are disappeared and Feed component not ms
I'm working on a React web application using React router.
In my App.js file i have imported header and home component.
In home component i have 2 components called Onlinebanks and Creditcard that i imported from online-banks.js and creditcard.js files.
When the user clicks link buttons in home.js component, the Onlinebanks and Creditcard components should render.
Instead i am getting an error called Error: Invariant failed: You should not use < Link> outside a < Router>.
Why it's not working?
INDEX.JS
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));
APP.JS
import React, { Component } from 'react';
import './App.css';
import Header from './components/header';
import Home from './components/home';
class Routes extends Component {
constructor(props){
super(props);
this.state = {
};
}
render(){
return (
<div className="wrapper">
<Header/>
<Home/>
</div>
);
}
}
export default Routes;
HOME.JS
import React from 'react';
import { Route, Switch, Link } from 'react-router-dom';
import Onlinebanks from './online-banks';
import Creditcard from './creditcard';
const Home = (props) => {
return (
<div className="section">
<div className="main-page">
<div className="tab-container">
<div className="tab-btns">
<Link to="/">
<div className="online-bank-btn">
Online pangad
</div>
</Link>
<Link to="/creditcard">
<div className="creditcard-btn">
Krediitkaart
</div>
</Link>
</div>
<Switch>
<Route path="/" exact component={Onlinebanks}/>
<Route path="/creditcard" exact component={Creditcard}/>
</Switch>
</div>
</div>
</div>
)
}
export default Home;
ONLINE-BANKS.JS
import React from 'react';
const Onlinebanks = (props) => {
return (
<div className="banks-container">
<input type="button" value="Pay" className="pay-btn" id="online-banks-pay"></input>
</div>
)
}
export default Onlinebanks;
CREDITCARD.JS
import React from 'react';
const Creditcard = (props) => {
return (
<div className="Creditcard-container">
<input type="button" value="Pay" className="pay-btn" id="creditcard-pay"></input>
</div>
)
}
export default Creditcard;
I don't see anywhere in your code where you imported BrowserRouter from react-router-dom which should wrap all the other components rendered by your top level componet (app.js) or entirely wrap the app component. so, first import { BrowserRouter as Router } from "react-router-dom" in index.js, then wrap App component with Router as follows
ReactDOM.render(<Router> <App /> </Router>, document.getElementById("root"));
alternatively you can wrap the retun statment in app.js with Router as follows after importing BrowserRouter as Router
return (
<Router>
<div className="wrapper">
<Header/>
<Home/>
</div>
</Router>
);
<Router> is an HOC component, so you need to use it at the top most level possible. Suggestion would be to create a separate Router component and use it within App.js file above div tag
<CustomRouter>
<div className="wrapper">
<Header/>
<Home/>
</div>
</CustomRouter>
you need to better understand how react-router-dom works.
visit here for complete routing guide react-router-dom
i found some major missings in your app.js file.
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/about">
<About />
</Route>
<Route path="/dashboard">
<Dashboard />
</Route>
</Switch>
i don't see this method in your app.js .
So I am new to ReactJS and is trying to figure it things how to have an app with a different header for the login page and then another header once the user was logged in.
I only want to have the very first page to have the LoginHeader and then the PostHeader as the main header once they get authenticated.
However, when I am on the my login page, whenever I click the sign in button I automatically get taken to my PostHeader page even though I routed my correct link. Everything in the PostHeader works fine, like when I click Home and Create they return the pages they are supposed.
My code is down below
index.js
import React from 'react';
import createHistory from 'history/createBrowserHistory';
import ReactDOM from 'react-dom';
import { Route, Switch, Router } from 'react-router-dom';
import Header from "./_components/header/header";
ReactDOM.render(
<Router history={createHistory()}>
<div>
<Header />
</div>
</Router>,
document.getElementById('root'),
);
Header.js
import React, {Component} from 'react';
import {Link,Route,withRouter, Switch, } from 'react-router-dom';
import PostHeader from './PostHeader';
import LoginHeader from './LoginHeader';
class Header extends Component{
render(){
if (window.location.pathname === '/') {
return(
<LoginHeader />
);
};
return(
<PostHeader />
);
}
}
export default Header;
LoginHeader.js
import React, {Component} from 'react';
import {Link,Route,withRouter, Switch} from 'react-router-dom';
import SignIn from '../signin/signin';
import TopProjects from '../create_projects/top_projects';
class LoginHeader extends Component{
render(){
return(
<div className="container">
<div>
<h3>The Web App</h3>
<nav>
<ul>
<li><Link to="/sign-in">Sign In?</Link></li>
<li><Link to="/top-projects">Top Projects</Link></li>
</ul>
</nav>
<hr />
</div>
<Switch>
<Route exact path="/sign-in" component={SignIn}/>
<Route path="/top-projects" component={TopProjects} />
</Switch>
</div>
);
}
}
export default LoginHeader;
PostHeader.js
import React, {Component} from 'react';
import {Link,Route} from 'react-router-dom';
import Home from '../home/home';
import CreateProjects from '../create_projects/create_projects';
class PostHeader extends Component{
render(){
return(
<div className="container">
<div>
<h3>The Web App</h3>
<nav>
<ul>
<li><Link to="/home">Home</Link></li>
<li><Link to="/create-projects">Create</Link></li>
</ul>
</nav>
<hr />
</div>
<Route path="/home" component={Home}/>
<Route path="/create-projects" component={CreateProjects} />
</div>
);
}
}
export default PostHeader;
I just want to have different headers for some pages.
That's because in your Header.js, you are only rendering the LoginHeader if you are in the root route.
if (window.location.pathname === '/') {
return(
<LoginHeader />
);
};
So when you click the sign in button, it redirects you to /sign-in, thus when Header is re-rendered, the condition will fall on the else statement which returns the PostHeader.
js and am using react-router-dom.
Say I have 2 files - 1. dashboard.js file
import React, { Component } from 'react';
import {Switch, Route, Link} from 'react-router-dom';
import WYSIWYG from './editor/wysiwyg';
export default class Dashboard extends Component{
render(){
return(
<div className="wrapper">
<Switch>
<Route exact path="/wysiwyg" component={WYSIWYG}/>
</Switch>
<ul id="DASHBOARD-MENU">
<li><Link to={{ pathname: '/wysiwyg'}}>WYSIWYG</Link></li>
</ul>
</div>
);
}
}
Note the ul with id="DASHBOARD-MENU" above
2nd - wysiwyg.js file
import React, { Component } from 'react';
export default class Wysiwyg extends Component{
render(){
return(
<div id="WYSIWYG-CONTAINER">
</div>
);
}
}
Note the div with id="WYSIWYG-CONTAINER" in the above snippet
My problem is:
After redirection to WYSIWYG container from my dashboard, I can still see the - <ul id="DASHBOARD-MENU" .. rendered below the <div id="WYSIWYG-CONTAINER ...
What I understood - is the component WYSIWYG is rendered replacing <Route declared in my dashboard.js file.
What I want:
I don't want the "DASHBOARD-MENU" element to render in my "WYSIWYG" page.
Is it possible?
The desired behavior can be obtained by considering both as different routes, and hence rendering only one of them depending on the path:
import React, { Component } from 'react';
import {Switch, Route, Link} from 'react-router-dom';
import WYSIWYG from './editor/wysiwyg';
const Dashboard = () => (
<ul id="DASHBOARD-MENU">
<li><Link to={{ pathname: '/wysiwyg'}}>WYSIWYG</Link></li>
</ul>
);
export default class Dashboard extends Component{
render(){
return(
<div className="wrapper">
<Switch>
<Route exact path="/" component={Dashboard} />
<Route exact path="/wysiwyg" component={WYSIWYG}/>
</Switch>
</div>
);
}
}