Invalid login-check system with a custom hook - javascript

AuthRoute.jsx
import React from 'react';
import { useAuth } from 'react-firebase-hooks/auth';
import { Route, Redirect } from 'react-router-dom';
function AuthRoute({ children, ...rest }) {
const { user } = useAuth();
return (
<Route
{...rest}
render={({ location }) =>
user ? (
children
) : (
<Redirect
to={{
pathname: '/login',
state: { from: location }
}}
/>
)
}
/>
);
}
export default AuthRoute;
App.jsx
import { auth } from "./components/base";
import { useAuthState } from "react-firebase-hooks/auth";
import React from "react";
import Home from "./pages/Home";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import Login from "./pages/Login";
import Register from "./pages/Register";
import MainPage from "./pages/MainPage";
import AuthRoute from "./pages/AuthRoute";
function App() {
const [user, loading] = useAuthState(auth);
return (
<div>
<Router>
<Routes>
<Route path="/" element={<Home />} />
<AuthRoute path="/mainpage" exact element={MainPage} />
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
</Routes>
</Router>
</div>
);
}
export default App;
The point is:
I created a custom hook AuthRoute.jsx which checks if the user is logged in via useAuth.
When a user tries to proceed to MainPage.jsx and if he's not logged in (Login.jsx) (I also connected my application to Firebase Auth so the information should be there), he can't proceed to MainPage.jsx.
However, if the user is logged in, he can proceed to MainPage.jsx.
I am facing this error in console.log:
Uncaught SyntaxError: The requested module '/node_modules/.vite/deps/react-router-dom.js?v=6310222e' does not provide an export named 'Redirect' (at AuthRoute.jsx:3:17)
I also asked ChatGPT to help me fix this issue but his solutions didn't work.
I'd appreciate if you guys can help me correct the code.

Related

Question about PrivateRoutes and to get navigated back to login page

Hi I need help getting my code to work so that when I try to log back in I won't be able to view the dashboard since I logged out. Right now its giving me a blank screen in my project and I think its because privateroute isn't a thing anymore? Not sure. This is my code in PrivateRoute.js:
import React, { Component } from 'react';
import { Route, Navigate } from 'react-router-dom';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
const PrivateRoute = ({ component: Component, auth: { isAuthenticated, loading },
...rest }) => (
<Route {...rest} render={props => !isAuthenticated && !loading ? (<Navigate to='/login' />) : (<Component {...props} />)} />
)
PrivateRoute.propTypes = {
auth: PropTypes.object.isRequired
};
const mapStatetoProps = state => ({
auth: state.auth
});
export default connect(mapStatetoProps)(PrivateRoute);
This is the code for the app.js:
import React, { Fragment, useEffect } from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import Navbar from './components/layout/Navbar';
import Landing from './components/layout/Landing';
import Register from './components/auth/Register';
import Login from './components/auth/Login';
import Alert from './components/layout/Alert';
import Dashboard from './components/dashboard/Dashboard';
import PrivateRoute from './components/routing/PrivateRoute';
// Redux
import { Provider } from 'react-redux';
import store from './store';
import { loadUser } from './actions/auth';
import setAuthToken from './utils/setAuthToken';
import './App.css';
if (localStorage.token) {
setAuthToken(localStorage.token);
}
const App = () => {
useEffect(() => {
store.dispatch(loadUser());
}, []);
return (
<Provider store={store}>
<Router>
<Fragment>
<Navbar />
<Routes>
<Route exact path='/' element={<Landing/>} />
</Routes>
<section className="container">
<Alert />
<Routes>
<Route exact path='/Register' element={<Register/>} />
<Route exact path='/Login' element={<Login/>} />
<PrivateRoute exact path='/dashboard' element={Dashboard} />
</Routes>
</section>
</Fragment>
</Router>
</Provider>
)};
export default App;
Please Help!
there is a recommended Protected Route implementation in the v6 react router docs you can follow.
DOCS IMPLEMENTATION
Your issue:
<Route {...rest} render={props => !isAuthenticated && !loading ?
(<Navigate to='/login' />) : (<Component {...props} />)} />
This Route is not up to date with v6, which I assume you are using, you need to update it.
Exact is also not supported anymore, there is no point in including it in your routes.
If you are not using v6 please update your post and include your react-router version.

react-router - handleLogin function

I have the following structure for my React.js application using React Router:
import React, { useState } from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import './App.css';
import Landing from './components/Landing/Landing';
import Home from './components/Home/Home';
import { AuthProvider } from "./context/AuthProvider";
function App() {
const [user, setUser] = useState(false);
const handleLogin = e => {
e.preventDefault();
setUser(true);
}
return (
<div className="App">
<Router>
<AuthProvider>
<Routes>
<Route exact path='/' handleLogin={handleLogin}
render={props => <Landing {...props} user={user.toString()}
handleLogin={handleLogin} />} />
<Route exact path='/home' element={ <Home /> } />
</Routes>
</AuthProvider>
</Router>
</div>
)
}
export default App
I want to create a function called handleLogin which will invoke setUser and flip the user value to true when we click "Log In"
When I save it, It show a blank page and on console it display
Matched leaf route at location "/" does not have an element. This
means it will render an with a null value by default
resulting in an "empty" page.
What's the easiest and right way to do?

react-router-Dom: Blank page after redirect multiple user on login in React

I have two(USER and ADMIN) users in my react project and I want to redirect them to their respected page after a successful login. To achieve this I created a standalone component called authenticatedRoute.js and wrap those components by AuthenticatedRoute component. Here are the codes
AuthenticatedRoute.js
import { useHistory } from "react-router-dom";
import { Route } from "react-router-dom";
const AuthenticatedRoute = ({ children, ...rest }) => {
const history = useHistory();
var tokenn = JSON.parse(localStorage.getItem("desta"));
var user_type = tokenn?.user.roles[0]; //USER or ADMIN
var loggedIn = tokenn?.user_status; //true
const redirect = () => {
try {
switch (user_type) {
case "USER":
return [history.push("/user"), children];
case "ADMIN":
return [history.push("/admin"), children];
default:
console.log("redirect");
}
} catch (err) {
return [history.push("/signin"), children];
}
};
return (
<Route
render={() => {
return loggedIn ? redirect() : history.push("/signin");
}}
/>
);
};
export default AuthenticatedRoute;
App.js (minimal code)
import "./App.css";
import Header from "./components/Header/Header";
import HeaderLinks from "./components/Header/HeaderLinks";
import Hero from "./components/Header/Hero/Hero";
import Login from "./components/auth/Login";
import {
BrowserRouter as Router,
Route,
Switch,
useHistory,
} from "react-router-dom";
import SignUp from "./components/auth/SignUp";
import ViewUserProfile from "./components/Admin/ViewUserProfile";
import AdminHeader from "./components/Admin/AdminHeader";
import ManageBusinessType from "./components/Admin/ManageBusinessType";
import ManageCompany from "./components/Admin/ManageCompany";
import UserDashboard from "./components/Users/UserDashboard";
import ViewProfile from "./components/Users/ViewProfile";
import { ResetPassword } from "./components/Users/ResetPassword";
import ChangePassword from "./components/Users/ChangePassword";
import { useEffect } from "react";
import AuthenticatedRoute from "./components/auth/authRoute/AuthenticatedRoute";
function App() {
return (
<Router>
<Switch>
<AuthenticatedRoute path="/" exact>
<Hero />
</AuthenticatedRoute>
<AuthenticatedRoute path="/admin" exact>
<AdminHeader />
</AuthenticatedRoute>
<AuthenticatedRoute path="/user" exact>
<UserDashboard />
</AuthenticatedRoute>
</Switch>
</Router>
);
}
export default App;
After a successful login it redirects me to the right user role page but it's empty page as the screenshot below.
How can I fix the Issue? I used react-router-dom#5.3.0
Thanks
You are rendering the result of a navigation action instead of JSX. AuthenticatedRoute should render either a Route rendering the routed content or a Redirect to the appropriate path.
Example:
If loggedIn is falsey, then redirect to "/signin", otherwise check the role the route should have access to, and if the role matches render a Route with the props passed through, otherwise redirect to the appropriate user/admin path.
import { useHistory } from "react-router-dom";
import { Route } from "react-router-dom";
const AuthenticatedRoute = ({ roles, ...props }) => {
const tokenn = JSON.parse(localStorage.getItem("desta"));
const user_type = tokenn?.user.roles[0]; //USER or ADMIN
const loggedIn = tokenn?.user_status; //true
return loggedIn
? roles.includes(user_type)
? <Route {...props} />
: <Redirect to={user_type === "USER" ? "/user" : "/admin"} />
: <Redirect to="/signin" />;
};
export default AuthenticatedRoute;
Specify the roles a route should accessible by.
function App() {
return (
<Router>
<Switch>
<AuthenticatedRoute path="/admin" roles={["ADMIN"]}>
<AdminHeader />
</AuthenticatedRoute>
<AuthenticatedRoute path="/user" roles={["USER"]}>
<UserDashboard />
</AuthenticatedRoute>
<Route path="/">
<Hero />
</Route>
</Switch>
</Router>
);
}

React page won't stop refreshing

I recently deployed my site on to a work test server. When I was building everything locally it seemed to be working fine. However once I went ahead and deployed it, the site now auto refreshes none stop almost every second. I have gone through my code and the small changes I made and can't seem to find what the cause of the issue is and why the site on our work vps is now refreshing over and over again. I'm hoping someone might have some insight on this. I have gone ahead and posted my App.jsx, index.js, and Home.jsx below. Any insight on the matter would be really appreciated.
I should also note that I went back and moved everything back local to see if there is something I might have done before sending it to the server. It would seem when I run this locally there are zero issues. I've also tested this on multiple browsers and asked a few colleagues to take a look and it seems it continues to refresh every second for them too and on multiple browsers
App.jsx
import "./app.scss";
import Home from "./pages/home/Home";
import Register from "./pages/register/Register";
import Watch from "./pages/watch/Watch";
import Login from "./pages/login/Login";
import {
BrowserRouter as Router,
Switch,
Route,
Redirect,
} from "react-router-dom";
import { useContext } from "react";
import { AuthContext } from "./context/authContext/AuthContext";
const App = () => {
const { user } = useContext(AuthContext);
return (
<Router>
<Switch>
<Route exact path="/">
{user ? <Home /> : <Redirect to="/register" />}
</Route>
<Route path="/register">
{!user ? <Register /> : <Redirect to="/" />}
</Route>
<Route path="/login">{!user ? <Login /> : <Redirect to="/" />}</Route>
{user && (
<>
<Route path="/movies">
<Home type="movie" />
</Route>
<Route path="/series">
<Home type="series" />
</Route>
<Route path="/watch">
<Watch />
</Route>
</>
)}
</Switch>
</Router>
);
};
export default App;
index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { AuthContextProvider } from "./context/authContext/AuthContext";
ReactDOM.render(
<React.StrictMode>
<AuthContextProvider>
<App />
</AuthContextProvider>
</React.StrictMode>,
document.getElementById("root")
);
Home.jsx
import Navbar from "../../components/navbar/Navbar";
import Featured from "../../components/featured/Featured";
import "./home.scss";
import List from "../../components/list/List";
import { useEffect, useState } from "react";
import axios from "axios";
const Home = ({ type }) => {
const [lists, setLists] = useState([]);
const [genre, setGenre] = useState(null);
const axiosInstance = axios.create({
baseURL: process.env.REACT_APP_API_URL,
});
useEffect(() => {
const getRandomLists = async () => {
try {
const res = await axiosInstance.get(
`lists${type ? "?type=" + type : ""}${
genre ? "&genre=" + genre : ""
}`,
{
headers: {
token:
"Bearer " +
JSON.parse(localStorage.getItem("user")).accessToken,
},
}
);
setLists(res.data);
} catch (err) {
console.log(err);
}
};
getRandomLists();
}, [type, genre, axiosInstance]);
return (
<div className="home">
<Navbar />
<Featured type={type} setGenre={setGenre} />
{lists.map((list) => (
<List list={list} />
))}
</div>
);
};
export default Home;
A new axiosInstance is created on every render, and it triggers useEffect change.
Move the axiosInstance creation out of the component.
const axiosInstance = axios.create({
baseURL: process.env.REACT_APP_API_URL,
});
const Home = ({ type }) => {
const [lists, setLists] = useState([]);
const [genre, setGenre] = useState(null);
// stuff
};
Does the route that contains the component refreshes infinitely?
That is because React Refresh causes component remount each time the state changes. In your case, you are creating an axios instance 1) not only not storing it in the useState ( you create it as a plain variable ), 2) but also on each component render;
That causes the React Refresh to go crazy. The reason why it works on local might be related to some Webpack stuff, but that doesn't matter much as you should configure axios differently anyways.
Solution:
Why not to set up default configuration that will be common for all the requests through the application?
import "./app.scss";
import Home from "./pages/home/Home";
import Register from "./pages/register/Register";
import Watch from "./pages/watch/Watch";
import Login from "./pages/login/Login";
import {
BrowserRouter as Router,
Switch,
Route,
Redirect,
} from "react-router-dom";
import { useEffect, useContext } from "react";
import { AuthContext } from "./context/authContext/AuthContext";
const App = () => {
useEffect( () => {
axios.defaults.baseURL = process.env.REACT_APP_API_URL;
}, [] )
const { user } = useContext(AuthContext);
return (
<Router>
<Switch>
<Route exact path="/">
{user ? <Home /> : <Redirect to="/register" />}
</Route>
<Route path="/register">
{!user ? <Register /> : <Redirect to="/" />}
</Route>
<Route path="/login">{!user ? <Login /> : <Redirect to="/" />}</Route>
{user && (
<>
<Route path="/movies">
<Home type="movie" />
</Route>
<Route path="/series">
<Home type="series" />
</Route>
<Route path="/watch">
<Watch />
</Route>
</>
)}
</Switch>
</Router>
);
};
export default App;
So that no instances are created, and defaults are configured correctly.
Then you use it like:
axios.post( '/someendpoint', { test : true } )
Let me know if it works!

React conditional rendering not triggering?

I am trying to change the contents of my Navbar and my Router via useContext and conditional rendering.
This is my App.js:
import "./App.css";
import axios from "axios";
import { AuthContextProvider } from "./context/AuthContext";
import MyRouter from "./MyRouter";
axios.defaults.withCredentials = true;
function App() {
return (
<AuthContextProvider>
<MyRouter />
</AuthContextProvider>
);
}
export default App;
This is my Router:
import React, { useContext } from "react";
import AuthContext from "./context/AuthContext";
import {
BrowserRouter as Router,
Switch,
Route,
Redirect,
} from "react-router-dom";
import MyNavBar from "./components/MyNavbar";
import "./App.css";
import Home from "./components/pages/Home";
import AboutUs from "./components/pages/AboutUs";
import Register from "./components/pages/Register";
import MyFooter from "./components/MyFooter";
import login from "./components/pages/login";
import ProfilePage from "./components/pages/ProfilePage";
function MyRouter() {
const { loggedIn } = useContext(AuthContext);
return (
<Router>
<MyNavBar />
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/about-us" component={AboutUs} />
{loggedIn === false && (
<>
<Route exact path="/register" component={Register} />
<Route exact path="/login" component={login} />
</>
)}
{loggedIn === true && (
<>
<Route exact path="/profile" component={ProfilePage} />
</>
)}
<Redirect to="404" />
</Switch>
<MyFooter />
</Router>
);
}
export default MyRouter;
My Navbar's conditional rendering works in the same way as the router. My problem is that neither of the conditional rendering fragments are working. For example, when my application starts, users are not logged in and the "loggedIn" value is false. With this logic, the routes "register" and "login" should be accessible, but they are not. Any advice or help would be greatly appreciated as I am quite new to using React.
Here is a screenshot of my console upon loading the application
This is my "AuthContext":
const AuthContext = createContext();
function AuthContextProvider(props) {
const [loggedIn, setLoggedIn] = useState(undefined);
async function getLoggedIn() {
const loggedInRes = await axios.get(
"http://localhost:5000/api/users/loggedIn"
);
setLoggedIn(loggedInRes.data);
}
useEffect(() => {
getLoggedIn();
}, []);
return (
<AuthContext.Provider value={{ loggedIn, getLoggedIn }}>
{props.children}
</AuthContext.Provider>
);
}
export default AuthContext;
export { AuthContextProvider };
Thanks for all the help guys, I learned a lot about the ProtectedRoute concept. My issue came from my Navigation Bar component. Instead of declaring my variable as an object, I declared loggedin like
const loggedIn = useContext(AuthContext);
All my errors were solved once I changed it to
const { loggedIn } = useContext(AuthContext);
Edited:
Instead of using your conditions in your main route, you can create a ProtectedRoute which Routes your component according to your condition.
import React, { useEffect } from "react";
import { Route, Redirect, useHistory } from "react-router-dom";
const ProtectedRoute = ({ component: Component, ...rest }) => {
const { loggedIn } = useContext(AuthContext);
return (
<Route
{...rest}
render={(props) =>
loggedIn() ? (
<Component {...props} />
) : (
<Redirect to='/login' />
)
}
/>
);
};
export default ProtectedRoute;
In your component you can change your logic with this:
<ProtectedRoute exact path="/" component={Home} />
<ProtectedRoute exact path="/about-us" component={AboutUs}/>
<Route exact path="/register" component={Register} />
<Route exact path="/login" component={login} />
<ProtectedRoute exact path="/profile" component={ProfilePage} />
This means that if you wanna protect a route you should route it with ProtectedRoute otherwise classic react route.
You can read about that ProtectedRoute concept here

Categories

Resources