I'm new with React. I'm using react-router-dom.
import React from 'react';
import { Router, Route, Switch, Link } from 'react-router-dom';
import Home from './components/home';
import Login from './components/login';
class App extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="app">
<Link to='/'>Home</Link>
<Link to='/login'>Login</Link>
<Switch>
<Route exact path='/' component={Home}/>
<Route path='/login' component={Login}/>
</Switch>
</div>
);
}
}
export default App;
I'm using this code everything work fine, but when I go to localhost:8080/login directly via de url I get a error Cannot GET /login but it goes well through a link <Link to='/login'>Login</Link>.
how can I fix it?
So this is often a tricky thing I deal with in regards to navigating with react.
By navigating directly to /login your React App hasn't actually rendered the highest parent or root and thus there really isn't a login component to find and render. Here's what I do when working with logins and home
<Route exact path="/" component={() => this.props.auth ? <DashboardContainer/> : <Redirect to="/" />}/>
This says if there isn't any auth (or local storage, or cookies, or whatever you're using to log them in) redirect back home or to / so they can click /login.
Basically you need your highest level component to mount virtually before you can do anything else. You can also make /login your landing page, so in this case merge / and /login. But the above example is modularized and dynamic.
Related
I am trying to make a multi page app with react routing.
I am have some questions as to how I should structure the routing in the react project.
I want to load my component in my app.js file. In my Home component I would like to have the ability to press a button which will take me to the Poems component, I want the code to be clean and structured into components, therefore I dont want to do all this in the app.js file.
If someone would explain to me how to best do this I can from there be able to route around to multiple pages afterwards depending on the page you are on. I dont want to have a global menu currently (I will want that in the Poems component later though).
Here is my current App.js file & Home.jsx component code just for a more easily adjustable experience for you guys!
Currently it is not optimized to work so if anyone knows a good routing solution for my issue, please give me an example of the routing fix.
Thanks alot
/Jacob
import React from 'react'
import { Route, BrowserRouter as Router, Routes } from 'react-router-dom'
import './App.scss'
import { Home, Poems, Favourites } from './Pages'
const App = () => {
return (
<Router>
<div className="app">
<Home />
<Routes> {/* I read that the Switch was replaces with Routes */}
<Route path="/" exact component={ Home } />
<Route path="/Poems" component={ Poems } />
<Route path="/Favourites" component={ Favourites } />
</Routes>
</div>
</Router>
)
}
export default App
import React from 'react'
import { Route, BrowserRouter as Router, Routes, Link } from 'react-router-dom'
import { Poems } from './Pages'
import './Home.scss'
const Home = () => {
return (
<Router>
<div>
<h1>Petry For All</h1>
<Routes>
<Route path="/Poems" component={ Poems } />
<Link to="/Poems">Poems</Link>
</Routes>
</div>
</Router>
)
}
export default Home
You don't need to (and actually shouldn't) duplicate the <Router> component in all of the route pages. It is only the root component that is acting as a router. So you can keep the App component the same, and then replace the Home component with the following:
import React from 'react'
import { Poems } from './Pages'
import './Home.scss'
const Home = () => {
return (
<div>
<h1>Petry For All</h1>
<Link to="/Poems">Poems</Link>
</div>
)
}
export default Home
The <Link> component resolves into an anchor element which, when clicked, navigates the user to the route passed into the to property.
Trying to learn react and I created a Navbar with a simple list of links that point to routes in App.tsx. As it's working currently, all my components display the Navbar. Including the Login component, which is not what I want.
The behavior I'm looking for would display the login component without the Navbar when the app is launched, so path "/". And then once they click the login button, it would "log them in" and display a default component with the Navbar and allow them to move around the app.
Before I get into the state part, I need to know how I can go about achieving this first. I tried re-arranging the Navbar position in App.tsx to no avail (the Navbar contains links, so it has to be within a Router). All the other routes need the navbar as well, so it makes sense to put it first, except for login (or any other page I don't want to include the navbar).
I'll leave out my Navbar component since it just has links. But my App component looks like this, which hopefully is enough to explain what I'm missing:
App.tsx:
import * as React from "react";
import { useState } from "react";
import "./index.css";
import {
BrowserRouter as Router,
Switch,
Route,
Redirect,
} from "react-router-dom";
import Navbar from "./components/Navbar";
import VisitLog from "./components/VisitList";
import Dashboard from "./components/Dashboard";
import Profile from "./components/Profile";
import Login from "./components/Login"
export default function App() {
const [loggedIn, setLoggedIn] = useState(false);
return (
<div>
<Router>
<Navbar />
<Switch>
<Route exact path="/" />
<Route path="/profile" component={Profile} />
<Route path="/visits" component={VisitLog} />
<Route path="/dashboard" component={Dashboard} />
<Route path="/login" component={Login} />
</Switch>
</Router>
</div>
);
}
Do I need to rework my navbar and routes completely or is there a relatively simple way to make exceptions to which components see the navbar?
Also, I'm open to other ideas to achieve a similar effect. It's just a standard practice in any website to display login page if not logged in, but I wasn't able to find much for my navbar display purposes.
Pretty simple. I must be missing something.
Thanks!
What if you avoid render navbar if user is not logged in and redirect it to '/login'path.
return (
<div>
<Router>
{lodggedIn ? <Navbar /> : <Redirect to="/login"/>}
<Switch>
<Route path='/login' component={() => <Login setLogin={(islogged)=> setIslogged(isLogged)}/>}/>
</Switch>
</Router>
</div>
);
And in your Login component you pass the result of the login attempt to the setLogin function in props.
example:
function attemptLogin(){
let result = get login results
this.props.setLogin(result);
}
import Sign from './sign.js'`
import Login from './login.js'
import {BrowserRouter, Link} from 'react-router-dom'
class App extends React.Component{
render(){
return(
<BrowserRouter>
<Link to="/login">Login</Link>
<Link to="/signup">Sign Up</Link>
<Route exact path="/login" >
<Login />
</Route>
<Route path="/signup">
<Signup />
</Route>
</BrowserRouter>
)}}
export default App;
So my problem is, Upon compiling this code, it only loads the children component. But can you help me to understand that how can I load whole page instead of loading these components into same page.
I tried these methods though.
1. Tried to make a new page which loads these two pages, such as login and sign up. But that leaves me with two links, which I do not want.
2. I tried changing the links using above method from each component, and loads the page in parent app. But it gave me error of computed match.
Please I am a new learner, help me out.
The earlier version of React had this bug, on updating the link. The previous version was not refreshing the page.
The route is working fine on local. However, it is not working after the build except the home route which is working but the two route it gives 404 not found result. The login and registration component its a plain form not connected to any API or server and the home component its just a return plain text info.
I'm new to react so I don't know an idea why not working on build but perfectly working on development.
I tried to run both on serve build localhost:5000 and upload to the server but not working also.
import React, { Component } from 'react';
import {
Route,
Switch,
BrowserRouter as Router
} from 'react-router-dom';
import LoginComponent from './component/login/login'
import RegisterComponent from './component/registration/register'
import Home from './component/dashboard/template/home'
const NoMatch = ({location}) =>(
<div>
<h3>No Match for {location.pathname}</h3>
</div>
)
class App extends Component {
render() {
return (
<Router>
<Switch>
<Route exact path='/' component={Home} />
<Route path='/login' component={LoginComponent} />
<Route path='/register' component={RegisterComponent} />
<Route component={NoMatch} />
</Switch>
</Router>
);
}
}
export default App;
This is most likely an issue to do with how your server is set up. When visit the page, /login, the server is looking for a file called /login in the root. You need to configure a single entry-point to the server at index.html
In Apache this would be configured in .htaaccess or in nginx you can use a rewrite
I'm trying to embrace the react-router 4 philosophy of having routing spread throughout the app instead of one central place. For brevity, <App> effectively spits out the following in its render():
<BrowserRouter>
<Link to='/' />
<Link to='/linkb' />
<Switch>
<Route exact path='/' component={ComponentA}>
<Route exact path='/linkb' component={ComponentB>
</Switch>
</BrowserRouter>
...
So far so good: the nav links help me to route to the corresponding components A and B and my 2 page app works fine.
The problem I'm having is that, inside componentB, now I want it to have its own child routes. Though these routes will be 'grandchildren' of <App/>, I see no reason why <App/> should know or care about them. I built this (surrounding content and css stuff mostly ripped out for clarity):
Component B
import React, { Component } from "react";
import { BrowserRouter, Switch, Route, Link } from 'react-router-dom';
import ComponentC from './ComponentC';
import ComponentD from './ComponentD';
export default class ComponentB extends Component {
constructor(props) { super(props);}
render() {
return (
<div>
<div>
<Link to='/linkb/c' className='btn'>link C</Link>
<Link to='/linkb/d' className='btn'>link D</Link>
</div>
{this.props.children}
<Switch>
<Route exact path="linkb/c" component={ComponentC}/>
<Route exact path="linkb/d" component={ComponentD}/>
</Switch>
</div>
);
}
}
When I click link C or link D, the url updates in the browser bar but nothing changes on the page / the new component is not rendered. What am I doing wrong?
OK - so the only way I've gotten this to work is to stop hardcoding the paths in my child components, and use the path segments passed in via react-router. Since these evaluate to the same thing (I think) I'm unsure why this fixes my problem, but it does:
<Link to={`${this.props.match.path}/c`}>link c </Link>
<Link to={`${this.props.match.path}/d`}>link d </Link>
And that works!! No idea why! If someone can explain why I'll accept their answer instead of mine.
update: appears to have been a case of absolute vs relative urls. Using props.match.path avoid that kind of confusion.