Not Able to render new Component on link change - node.js

Actually when ever a person click's on Sign in Button the link change but the component on that page does not renders
App.js
import { BrowserRouter as Switch, Route } from 'react-router-dom';
const App = () => (
<Switch>
<Route path="/" exact component={Join} />
<Route path="/call" exact component={Call} />
</Switch>
);
export default App;
Join.js
return (
<div className="container">
<div><input id="room" placeholder="room name" onChange={(event)=>setRoom(event.target.value)}></input></div>
<BrowserRouter>
<Link onClick={event => (!room) ? event.preventDefault() : null} to={`/call?room=${room}`}>
<button className="button mt-20" type="submit" onClick={run}>Sign In</button>
</Link>
</BrowserRouter>
</div>
);
}
export default Join;
Call.js
const Call = () => {
return (
<div>
<h1>jhjcjc</h1>
</div>
);
}
export default Call;
Please look over this error many developer's are facing this problem.

In your Join component, there is no need to wrap Link in a BrowserRouter. Check out the working demo here.

Related

useeffect hook only runs when page refresh in a react-web-app

As in the question, useeffect hook only runs when I refresh the page in a react-web-app. Here is the main App.js:
import Chat from './Chat';
function App() {
return (
<div className="app">
<div className="app__body">
<Router>
<Sidebar />
<Switch>
<Route path='/rooms/:roomId'>
<Chat />
</Route>
<Route path="/">
<Chat />
</Route>
</Switch>
</Router>
</div>
</div>
);
}
And here is the Chat.js component:
function Chat() {
const [roomName, setRoomName] = useState("");
const { roomId } = useParams();
useEffect(() => {
if(roomId) {
db.collection("rooms").doc(roomId).
onSnapshot(snapshot => (
setRoomName(snapshot.data().name)
))
}
}, [roomId]);
return ( ......my divs )
}
When I click the roomNames on the sidebar, the page link instantly changes without refresh, I mean the "roomId", but it doesn't enter into useEffect hook without refreshing the page, therefore it doesn't change the displayed roomName lively in the app.
Any ideas?

react-router-dom cannot render page [duplicate]

I am building a Netflix clone application, and I am using react-router-dom v5 to switch between different pages. However, when I click the Link tag in Navbar.jsx, the URL changes, but the corresponding component doesn't render. I have consulted numerous StackOverflow posts on this topic, however, I can't get it to work. Below is the code. Please help me, as I'm stuck on this for 3 days 😥.
What it should show, when navigating to /series from /:
What it is actually showing:
index.js
import React from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
const container = document.getElementById("root");
const root = createRoot(container);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
App.jsx
import React from "react";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import "./app.scss";
import Home from "./pages/home/Home";
import Watch from "./pages/watch/Watch";
const App = () => {
return (
<Router>
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/movies">
<Home type="movies" />
</Route>
<Route path="/series">
<Home type="series" />
</Route>
<Route path="/watch">
<Watch />
</Route>
</Switch>
</Router>
);
};
export default App;
Home.jsx
import React from "react";
import Featured from "../../components/featured/Featured";
import Navbar from "../../components/navbar/Navbar";
import "./home.scss";
const Home = ({ type }) => {
return (
<div className="home">
<Navbar />
<Featured type={type} />
</div>
);
};
export default Home;
Navbar.jsx
import React, { useState } from "react";
import "./navbar.scss";
import { Link } from "react-router-dom";
const Navbar = () => {
const [isScrolled, setIsScrolled] = useState(false);
window.onscroll = () => {
setIsScrolled(window.scrollY === 0 ? false : true);
return () => window.onscroll == null;
};
return (
<div className={`navbar ${isScrolled ? "scrolled" : ""}`}>
<div className="container">
<img src="./netflix_logo.jpg"
alt="netflix logo"
/>
<Link to="/" className="link">
<span>Home</span>
</Link>
<Link to="/series" className="link">
<span>Series</span>
</Link>
<Link to="/movies" className="link">
<span>Movies</span>
</Link>
<Link to="" className="link">
<span>New and Popular</span>
</Link>
<Link to="" className="link">
<span>My List</span>
</Link>
</div>
</div>
);
};
export default Navbar;
Featured.jsx
import "./featured.scss";
import { IoMdPlay } from "react-icons/io";
import { FiInfo } from "react-icons/fi";
const Featured = ({ type }) => {
return (
<div className="featured">
{type && (
<div className="category">
<span style={{ color: "white" }}>
{type === "movies" ? "Movies" : "TV Series"}
</span>
<select name="genre" id="genre">
<option>Genre</option>
<option value="adventure">Adventure</option>
<option value="comedy">Comedy</option>
<option value="crime">Crime</option>
<option value="fantasy">Fantasy</option>
<option value="historical">Historical</option>
<option value="horror">Horror</option>
<option value="romance">Romance</option>
<option value="sci-fi">Sci-fi</option>
<option value="thriller">Thriller</option>
<option value="western">Western</option>
<option value="animation">Animation</option>
<option value="drama">Drama</option>
<option value="documentary">Documentary</option>
</select>
</div>
)}
<img
src="https://m.media-amazon.com/images/M/MV5BNzM4OTkzMjcxOF5BMl5BanBnXkFtZTgwMTkxMjI1MTI#._V1_.jpg"
alt="featured"
/>
<div className="info">
<img
src="https://occ-0-1432-1433.1.nflxso.net/dnm/api/v6/LmEnxtiAuzezXBjYXPuDgfZ4zZQ/AAAABUZdeG1DrMstq-YKHZ-dA-cx2uQN_YbCYx7RABDk0y7F8ZK6nzgCz4bp5qJVgMizPbVpIvXrd4xMBQAuNe0xmuW2WjoeGMDn1cFO.webp?r=df1"
alt=""
/>
<span className="desc">
When a beautiful stranger leads computer hacker Neo to a forbidding
underworld, he discovers the shocking truth - the life he knows is the
elaborate deception of an evil cyber-intelligence.
</span>
<div className="buttons">
<button className="play">
<IoMdPlay className="button-logo" />
<span>Play</span>
</button>
<button className="more">
<FiInfo className="button-logo" />
<span>More Info</span>
</button>
</div>
</div>
</div>
);
};
export default Featured;
There's a compatibility issue between pre-5.3.3 versions of react-router-dom#5 and react#18.
Github Issue #7870
PR #8831 merged to address issue - Fix was merged on May 18th, 2022, react-router-dom v5.3.3.
Solutions
Bugfix was merged into v5.3.3. Update to react-router-dom#5.3.3 or higher.
From the project's root directory run:
npm uninstall -S react-router-dom
npm install -S react-router-dom#5.3.3 (or #latest)
Revert back to React 17 (or React 17 syntax) and fix up the index.js file.
import { StrictMode } from "react";
import ReactDOM from "react-dom";
import App from "./App";
ReactDOM.render(
<StrictMode>
<App />
</StrictMode>,
document.getElementById("root")
);
Make the React.StrictMode component a child/descendent of the router component. Comment.
Replace:
<React.StrictMode>
...
<BrowserRouter>
...
</BrowserRouter>
</React.StrictMode>
with:
<BrowserRouter>
<React.StrictMode>
...
</React.StrictMode>
</BrowserRouter>
Upgrade to react-router-dom#6 and fix up the routes.
const App = () => {
return (
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/movies" element={<Home type="movies" />} />
<Route path="/series" element={<Home type="series" />} />
<Route path="/watch" element={<Watch />} />
</Routes>
</Router>
);
}
First Solution and Best Solution:
If you use are using React Router 5.3.x, check whether it is 5.3.3 in your package.json file.
If it is not 5.3.3 uninstall the last version then install the bug-free version which has been resolved by John and updated in version 5.3.3.
npm uninstall -S react-router-dom
npm install -S react-router-dom#5.3.3
Second Solution:
React has launched its StrictMode in its latest update.
you can see it in an index.js file
index.js
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
So here your React Router is in the child component. And we have to make it a parent component.
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<BrowserRouter>
<React.StrictMode>
<App />
</React.StrictMode>
</BrowserRouter>
);
Third Solution:
Remove the Strict mode from the index.js file
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<BrowserRouter>
<App />
</BrowserRouter>
);

page does not redirect after setting token with localstorage

I am following the tutorial below to create a token system for my login application.
https://www.digitalocean.com/community/tutorials/how-to-add-login-authentication-to-react-applications
Here is my code:
App.js:
import logo from './logo.svg';
import './App.css';
import "bootstrap/dist/css/bootstrap.min.css";
import useToken from './components/useToken';
import Navbar from './components/Navbar';
import AudioDropzone from './components/AudioDropzone';
import {
BrowserRouter as Router,
Switch,
Route,
Link,
useLocation
} from "react-router-dom";
import Upload from './pages/Upload';
import Manage from './pages/Manage';
import Menu from './pages/Menu';
import Admin from './pages/Admin';
import Login from './pages/Login';
import { useEffect, useState } from 'react';
<script src="https://unpkg.com/boxicons#latest/dist/boxicons.js"></script>
function App() {
const { token, setToken } = useToken();
console.log(token)
if(!token) {
return(
<div className="App">
<div className="row">
<div class="col-2">
</div>
<div class="col-9">
<Login setToken={setToken} />
</div>
</div>
</div>
);
}
return (
<div className="App">
<Router>
<head>
<link rel="stylesheet" href="boxicons.min.css" />
</head>
<div className="row" >
<div class="col-2">
</div>
<div class="col-9">
<Switch>
<Route path="/upload">
<Upload customer_id={token}/>
</Route>
<Route path="/manage">
<Manage customer_id={token} />
</Route>
<Route path="/menu">
<Menu customer_id={token} />
</Route>
<Route path="/admin">
<Admin />
</Route>
<Route path="/admin/upload">
<Upload />
</Route>
<Route path="/admin/manage">
<Manage />
</Route>
<Route path="/admin/menu">
<Menu />
</Route>
</Switch>
</div>
</div>
</Router>
</div>
);
}
export default App;
useToken.js:
import { useState } from 'react';
export default function useToken() {
const getToken = () => {
const tokenString = localStorage.getItem('token');
const userToken = JSON.parse(tokenString);
return userToken?.token
};
const [token, setToken] = useState(getToken());
const saveToken = userToken => {
localStorage.setItem('token', JSON.stringify(userToken));
setToken(userToken.token);
};
return {
setToken: saveToken,
token
}
}
Currently, when login is successful, it just clears the fields and shows the same login page again without showing the second version of App with all of my content. The issue is that the token value is not being updated and populated. I have verified that upon logging in token is updated to an integer value like 13.
This is seen when I log the value of userToken in useToken.js:
const saveToken = userToken => {
console.log(userToken) //returns 13
localStorage.setItem('token', JSON.stringify(userToken));
setToken(userToken.token);
};
Let me know what I am doing wrong!
I believe the bug is in the saveToken function.
setToken(userToken.token); should be setToken(userToken);
You don't need the .token because userToken is not an object. It is just an integer value.

How to redirect page after login in react.js

I am new to reactjs and trying to redirect the page after a user registers. Here is my App.js, which has a register input.
import React, { useState } from "react";
import './App.css';
import axios from 'axios';
function App() {
const [registerUsername, setRegisterUsername] = useState("");
const [registerPassword, setRegisterPassword] = useState("");
const [registerPasswordAgain, setRegisterPasswordAgain] = useState("");
const [registerEmail, setRegisterEmail] = useState("");
const register = () => {
axios({
method: "post",
data: {
registerUsername,
registerPassword,
registerPasswordAgain,
registerEmail
},
withCredentials: true,
url: "http://localhost:4000/register"
}).then((res) => console.log(res));
}
return (
<div className="App">
<div class = "topnav">
<a class="active" href="/register.html">Register </a>
<a class="active" href="/play.html">Play</a>
</div>
<div>
<h1>Register</h1>
<input placeholder ="Enter your username" onChange={e => setRegisterUsername(e.target.value)} />
<input type="password" placeholder ="Enter your password" onChange={e => setRegisterPassword(e.target.value)}/>
<input type="password" placeholder ="Enter your password again" onChange={e => setRegisterPasswordAgain(e.target.value)} />
<input placeholder ="Enter your email" onChange={e => setRegisterEmail(e.target.value)} />
<button onClick={register}>Submit</button>
</div>
</div>
);
}
this sends the registration username/password to my backend which is written in node.js. Assuming I send back a 200 OK status, or something that indicates that the user has registered, how can I redirect this page to another, lets say a login page? Do I need to create a class that extends component?
Just wondering where to go from here.
Thanks
use React-Router-dom
and in react we don't use anchor tag because react is SPA (Single page application), so use LINK tag
simple Example
index.js
import {BrowserRouter} from 'react-route-dom'
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>,
app.js
import {Switch,Rout,Link} from 'React-router-dom'
<div>
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/users"> {/add your redirect path/}
<Users /> {/Users components will render after the URL changes }
</Route>
<Route path="/" exact>
<Home />
</Route>
</Switch>
<Link to="/user">
<button>
Login
</button>
</Link>
</div>
using react-router-dome Redirect component you can redirect your page to abother page.
in your case you can store a boolean state and make it true when user suucessfully logged in.
import { Redirect } from "react-router-dom";
....
const [logged,setLogged] = useState(false)
.....
url: "http://localhost:4000/register"
}).then((res) => if(res.Sucess){
setLogged(true)
};
in your main component. you can add a redirect component like.
<div className="App">
{logged && <Redirect to="redirect-url" />}

React Router Param bug

EDIT: I found the issue, I went ahead and double checked my Header Component. I was using a relative path "login" as opposed to an absolute path "/login". When I switched from "login" to "/login" the issue was fixed.
I am having issues with react router. I have the App Class component where I locate all my routes. The issue is that when I go to the "Products" page (http://localhost:3000/products) I can link directly to the "ProductPage" where I get the route "http://localhost:3000/products/Scotts"; however when I navigate from that route to another route insted for example the "LoginPage" I get the following route "http://localhost:3000/products/login" as opposed to "http://localhost:3000/login". I will share the important code snippets below.
<Router>
<div className="App">
<ScrollToTop />
<Header/>
<Switch >
<Route exact path="/" component={ LandingPage }/>
<Route exact path="/login" component={ LoginPage }/>
<Route exact path="/products" component={ Products }/>
<Route
exact
path="/products/:product"
render={props => {
return <ProductPage {...props} />;
}}
/>
<Route path="resetPassword/:id" component={ChangePassword} />
</Switch>
<Footer />
</div>
</Router>
Here I am linking from the Products route to the Product's single page route:
{currentProducts.map(item => {
const { image, title, price, stock } = item;
return (
<div className="product-wrap" key={uuid()}>
<Link
to={{
pathname: `${location.pathname}/${item.title}`,
state: {
item: item,
inStock: stock
}
}}
>
<div>
<div className="product">
<div className="circle">
<img alt="item" src={image} />
</div>
</div>
</div>
</Link>
<div
style={{ textDecoration: "none", color: "black" }}
className="title"
>
{title}
</div>
<div
style={{ textDecoration: "none", color: "black" }}
className="price"
>
${price}
</div>
</div>
);
})}

Resources