I just started learning react router.
I am trying with a fairly basic example.
As I am trying with different routes, these routes are accessible when I try to hit them explicitly but when I am loading the page, its not loading the desired route. Can anyone please help me where I am making mistake.
import './App.css';
import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap/dist/js/bootstrap.js';
import Header from './components/Header';
import ProductCard from './components/ProductCard';
import ProductPage from './components/ProductPage';
import Cart from './components/Cart';
import { useSelector } from 'react-redux';
import LoginForm from './components/LoginForm';
import { useState, useEffect } from 'react';
import { Route, Switch, BrowserRouter } from 'react-router-dom';
function App() {
const showCartOption = useSelector(state => state.cart.showCartOption);
const isAuthenticated = useSelector(state => state.auth.isAuthenticated);
console.log("test - " + showCartOption + " " + isAuthenticated);
return (
<div class="m-3 shadow p-2">
<Header></Header>
<ProductPage />
<div class="row" >
<BrowserRouter>
{!isAuthenticated &&
<Route path="/login">
<LoginForm />
</Route>
}
{isAuthenticated && showCartOption &&
<ProductPage />
}
{isAuthenticated &&
<Route path='/products'>
<ProductPage />
</Route>
}
{isAuthenticated && !showCartOption &&
<Route path='/cart'>
<Cart />
</Route>
}
{!isAuthenticated && <LoginForm></LoginForm>}
</BrowserRouter>
</div>
</div >
);
}
export default App;
on loading the above snippet, console shows the value of flags as
showCartOption - true
isAuthenticated - false
I thought that it could be because it may go to every block until the end. I am not sure how this would work since I have added multiple conditions, so I also tried it with one single condition (added modified snippet below). In this case I was expecting that it would load the /login page. but that is also not happening. Its landing on the page where there is no path and hence no component.
2nd attempt :
import './App.css';
import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap/dist/js/bootstrap.js';
import Header from './components/Header';
import ProductCard from './components/ProductCard';
import ProductPage from './components/ProductPage';
import Cart from './components/Cart';
import { useSelector } from 'react-redux';
import LoginForm from './components/LoginForm';
import { useState, useEffect } from 'react';
import { Route, Switch, BrowserRouter } from 'react-router-dom';
function App() {
const showCartOption = useSelector(state => state.cart.showCartOption);
const isAuthenticated = useSelector(state => state.auth.isAuthenticated);
console.log("test - " + showCartOption + " " + isAuthenticated);
return (
<div class="m-3 shadow p-2">
<Header></Header>
<ProductPage />
<div class="row" >
<BrowserRouter>
{!isAuthenticated &&
<Route path="/login">
<LoginForm />
</Route>
}
</BrowserRouter>
</div>
</div >
);
}
export default App;
Related
This has been bugging me for a long time, and my head just can't seem to come up with a solution that works fluently. I will try to be short:
I have a React app where I update my Navbar based on an access token being stored as a cookie or not (user authenticated or not). But in order for my Navbar to update whether the user is authenticated, I have to refresh the page. I believe it is because my Navbar is being rendered way up (in?) the component tree, and does not get re-rendered whenever I visit a new page (only when I refresh).
What is the best way to render my Navbar component so that every page shares the same component, BUT the Navbar re-renders on every new page visited? Or is this even a wise thing to do?
Let me know if I am not explaining myself clearly.
index.jsx
import React from "react";
import ReactDOM from "react-dom";
import { App } from "./components/App";
import { BrowserRouter } from "react-router-dom";
import "./styles/styles.css";
import { PublicClientApplication } from "#azure/msal-browser";
import { MsalProvider } from "#azure/msal-react";
import { msalConfig } from "./lib/authConfig";
const msalInstance = new PublicClientApplication(msalConfig);
ReactDOM.render(
<MsalProvider instance={msalInstance}>
<BrowserRouter>
<App />
</BrowserRouter>
</MsalProvider>,
document.getElementById("root")
);
App.jsx
import React from "react";
import { Router } from "./Router";
import { Navbar } from "./Navbar";
export function App() {
return (
<div>
<Navbar />
<Router />
</div>
);
}
Router.jsx
import { Route } from "react-router-dom";
import React from "react";
import { MainPage } from "./MainPage";
import { LoginPage } from "./LoginPage";
import { GoogleLogin } from "./GoogleLogin";
import { GoogleLoginCallback } from "./GoogleLoginCallback";
import { GoogleLogout } from "./GoogleLogout";
import { NewArticle } from "./NewArticle";
export function Router() {
return (
<div>
<Route exact path="/" component={MainPage} />
<Route exact path="/login" component={LoginPage} />
<Route exact path="/login/google" component={GoogleLogin} />
<Route exact path="/logout/google" component={GoogleLogout} />
<Route exact path="/newArticle" component={NewArticle} />
<Route
exact
path="/login/google/callback"
component={GoogleLoginCallback}
/>
</div>
);
}
Navbar.jsx
import React, { useEffect, useState } from "react";
import { NavLink } from "react-router-dom";
import { useIsAuthenticated, useMsal } from "#azure/msal-react";
import { fetchJSON } from "../lib/fetchJSON";
export function Navbar() {
const activeStyle = {
borderBottom: "10px solid white",
};
const [username, setUsername] = useState();
const { accounts } = useMsal();
const name = accounts[0] && accounts[0].name;
const hasCookie = document.cookie.startsWith("access_token");
const isAuthenticated = useIsAuthenticated();
useEffect(async () => {
const res = await fetchJSON("/api/login/google");
if (hasCookie) {
setUsername(res.userinfo.given_name);
}
}, []);
return (
<>
<div className={"navbar-container"}>
<NavLink exact to="/" activeStyle={activeStyle}>
Home
</NavLink>
<NavLink exact to="/login" activeStyle={activeStyle}>
Login-portal
</NavLink>
{isAuthenticated ? (
<NavLink exact to="/newArticle" activeStyle={activeStyle}>
New Article
</NavLink>
) : (
<div />
)}
{isAuthenticated || hasCookie ? (
<p className="logged-in">
Logged in as {username} {name}
</p>
) : (
<p className="logged-in">Not logged in</p>
)}
</div>
</>
);
}
I have installed react-router-domV6-beta.
By following the example from a website I am able to use the new option useRoutes I have setup page routes and returning them in the App.js file.
After saving I am getting the following error:
Error: Error: useLocation() may be used only in the context of a
component.
App.js
import "./App.css";
import react, { useState, useEffect } from "react";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import _ from "lodash";
import Cast from "./Cast";
import list from "./list";
import Footer from "./Footer";
import DetailLayout from "./DetailLayout";
function App() {
const [charnames, setCharnam] = useState("");
function charname(names) {
setCharnam(names);
}
function castDetail(everycast) {
return (
<Cast
key={everycast.id}
url={everycast.url}
name={everycast.name}
castp={charname}
/>
);
}
const cc = charnames;
const p = "/" + cc;
//const p="/haha h";
const res = p.replace(/ /g, "");
return (
<div className="App">
<div className="overview">{list.map(castDetail)}</div>
{/* <DetailLayout /> */}
{console.log(charnames)}
<Router>
<Cast />
<Routes>
<Route exact path={res} element={<DetailLayout />} />
</Routes>
</Router>
<Footer />
</div>
);
}
export default App;
Cast.js
import react from "react";
import { NavLink } from "react-router-dom";
export default function Cast(props) {
function setpath() {
props.castp(props.name);
}
const path = "/" + props.name;
return (
<div className="cast">
{/* <Link to="/about">About</Link> */}
{/* <NavLink to="/about">About</NavLink> */}
<NavLink to={path}>
<img onClick={setpath} src={props.url} />{" "}
</NavLink>
<p>{props.name}</p>
</div>
);
}
this error simply says wrap your useLocation() inside
<Router> </Router>
all react-router-dom hooks and functions should be used inside
<BrowserRouter> </BrowserRouter>
otherwise they simply don't work
When I go to root link ("http://localhost:3000") jsx of the ProductListing component is not displayed but I can see console.log message that is written in ProductListing component.
import './App.css';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import Header from './containers/Header';
import ProductListing from './containers/ProductListing.js';
import ProductDetail from './containers/ProductDetail';
function App() {
return (
<div className="App">
<Router>
<Header/>
<Switch>
<Route path="/" exact component={ProductListing}/>
<Route path="/product/:productId" component={ProductDetail}/>
<Route>404 Not Found</Route>
</Switch>
</Router>
</div>
);
}
export default App;
import React from 'react'
import { useSelector } from 'react-redux'
const ProductListing = () => {
const products = useSelector(state => state)
console.log(products)
return (
<div>
<h1>ProductListing</h1>
</div>
)
}
export default ProductListing
Your error is laying on the import statement
Change:
import ProductListing from './containers/ProductListing.js';
To:
import ProductListing from './containers/ProductListing';
I am trying to add the live website URL i.e "https://covid19statswebsite.netlify.app/" so that when I click on my Button it should redirect me to the above URL. How can I do that?
Any Suggestions?
below is my Button,
import React from "react";
import "./Banner.css"
import BannerVideo from './videos/video-2.mp4'
import {Button} from "react-bootstrap";
import {useHistory} from "react-router-dom";
// import axios from './axios'
// import requests from "./Request";
function Banner(){
const history = useHistory()
return(
<div className="banner-container">
<video src={BannerVideo} autoPlay loop muted/>
<h1>ADVENTURE AWAITS</h1>
<p>What are you waiting for?</p>
/////////// Button That needs to redirect it ///////////////////////////////////////////////////////
<div className="banner-buttons">
<br/><br/><Button onClick={() => history.push("/covid")} className="covid"><span>COVID-19 Status</span></Button>
</div>
</div>
);
}
export default Banner
This is my App.js file which imports the Banner.js file above for Routes. I am not sure that the thing I want will happen with Routes or not. So I'd really love to know any other alternative if present.
import React, {useEffect} from 'react';
import './App.css';
import HomeScreen from "./screens/HomeScreen";
import LoginScreen from "./screens/LoginScreen";
import ProfileScreen from "./screens/ProfileScreen"
import {auth} from "./firebase";
import {BrowserRouter as Router, Switch, Route} from 'react-router-dom';
import {useDispatch, useSelector} from "react-redux";
import {login, logout, selectUser} from "./features/userSlice";
import Spain from "./countries/Spain";
import Covid from './Covid.js'
function App() {
const user = useSelector(selectUser)
const dispatch = useDispatch();
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged(userAuth => {
if (userAuth){
dispatch(login({
uid: userAuth.uid,
email: userAuth.email
}))
}else {
dispatch(logout());
}
});
return unsubscribe
}, [dispatch]);
return (
<div className="App">
<Router>
{!user ? (
<LoginScreen/>
):(
<Switch>
<Route path="/profile">
<ProfileScreen/>
</Route>
<Route exact path="/">
<HomeScreen/>
</Route>
<Route path="/spain">
<Spain/>
</Route>
//////////////////// Covid part //////////////////////////////////////////////////////////
<Route path="/covid">
<Covid/>
</Route>
</Switch>
)}
</Router>
</div>
);
}
export default App;
Below is the Covid.js which I created to check whether the Route works or not.
import React from "react";
function Covid(){
return(
<div className="covid">
<h1>hello</h1>
</div>
)
}
export default Covid
Edit:
import { Link } from "react-router-dom";
<Link
to={{
pathname:
"https://.......",}}
target="_blank">
<Button>...</Button>
</Link>
try to put the link in a hyperlink.
<a
href="https://covid19statswebsite.netlify.app/"
target="_blank">
<Button>...</Button>
</a>
I have a starter screen with two buttons which are login and register. Here is the code for the same:
import React from 'react';
import Header from './Header.jsx';
import Authentication from './AuthenticateCard.jsx';
import { Redirect } from 'react-router-dom';
function StarterScreen() {
function loginClick()
{
return(<Redirect to= "/login" />);
alert("Tru");
}
function registerClick()
{
console.log("Register");
}
return (
<div>
<Header header="My Water Chain"/>
<div className="WhiteCard">
<div className="whiteSpace">
</div>
<Authentication text="Login" onClickaction={loginClick} />
<Authentication text="Register" onClickaction={registerClick}/>
</div>
</div>
);
}
export default StarterScreen;
Here is my main app.js file:
import React from 'react';
import StarterScreen from './components/StarterScreen.jsx';
import LoginScreen from './components/LoginScreen.jsx';
import RegisterScreen from './components/RegisterScreen.jsx';
import 'bootstrap/dist/css/bootstrap.min.css';
import './App.css';
import {BrowserRouter,Route,Switch} from 'react-router-dom';
function App() {
function loginClick()
{
console.log("Login");
}
function registerClick()
{
console.log("Register");
}
return (
<div className="App">
<BrowserRouter>
<Switch>
<Route component={StarterScreen} exact path="/"></Route>
<Route component={LoginScreen} exact path="/register"></Route>
<Route component={StarterScreen} exact path="/login"></Route>
</Switch>
</BrowserRouter>
</div>
);
}
export default App;
when I click on login it just freezes and nothing happens afterwards. Screen does respond but no login action takes place with a bunch of errors:
Try:
import React from 'react';
import Header from './Header.jsx';
import Authentication from './AuthenticateCard.jsx';
import { withRouter } from 'react-router-dom';
function StarterScreen(props) {
function loginClick()
{
props.history.push('/login');
}
function registerClick()
{
console.log("Register");
}
return (
<div>
<Header header="My Water Chain"/>
<div className="WhiteCard">
<div className="whiteSpace">
</div>
<Authentication text="Login" onClickaction={loginClick} />
<Authentication text="Register" onClickaction={registerClick}/>
</div>
</div>
);
}
export default withRouter(StarterScreen);
Note here, I added withRouter to wrap your component and imported it from react-router-dom. Then I'm using props.history.push to navigate
You should not return a Redirect within event handler in StarterScreen, you can take advantage of the withRoutes high oder component or using useHistory hook to have access to the history of the navigator and change the route by calling push with the route where you want to navigate to.
import { withRouter } from 'react-router-dom';
const StarterScreen = ({history}) => {
const loginClick = () => {
history.push("/login");
}
return <div>
<Header header="My Water Chain"/>
<div className="WhiteCard">
<div className="whiteSpace">
</div>
<Authentication text="Login" onClickaction={loginClick} />
<Authentication text="Register" onClickaction={registerClick}/>
</div>
</div>;
}
export default withRouter(StarterScreen);
The withRouter high order component will pass 3 properties to you component has props match, location and history.
You can learn more here withRouter
Here is my way to redirect, i created a file call redirect.tsx, and then you can call from other file:
import { useHistory, withRouter } from "react-router-dom";
const Redirect = (props: any) => {
const to = (props.to || '/');
let history = useHistory();
history.push(to);
window.location.reload();
return (
<>
</>
)
}
export default withRouter(Redirect);
Without window.location.reload(); browser still redirect but it can not show anything!
Good day!