react-router - handleLogin function - javascript

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?

Related

Invalid login-check system with a custom hook

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.

React v6-Redux Create PrivateRoutes

Im trying to create a PrivateRoutes in addition to the regular routes.
After login, the page is successfully re-direct to /home, however when I tried to open /work, the page will go back to /home. all the data from state.valid is also shows "unidentified" in /work.
I figured it out that inside the privateRoutes it check if valid.isAuthenticated is true or not. However since. valid.isAuthenticated is set to false as initial value in reducer, everytime I open /home or /work, it re-render /login and then render /home or /work.
How do I fix to not to render /login before opening other pages?
Here is my PrivateRoutes.js
import React from "react";
import { useSelector } from "react-redux";
import { Navigate } from "react-router-dom";
const PrivateRoute = ({ children }) => {
const valid = useSelector((state) => state.valid);
return valid.isAuthenticated ? children : <Navigate to="/login" />;
};
export default PrivateRoute;
here is my AppRouter.js
import React from "react";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import PrivateRoute from "./PrivateRoute";
import App from "../components/App";
import Login from "../components/Login";
import HomePage from "../components/HomePage";
import WorkPage from "../components/WorkPage";
const AppRouter = () => (
<BrowserRouter>
<div>
<NavigationBar />
<div>
<Routes>
<Route path="/" element={<App />} exact />
<Route path="/login" element={<Login />} exact />
<Route path="/home" element={<PrivateRoute><HomePage /></PrivateRoute>} />
<Route path="/work" element={<PrivateRoute><WorkPage /></PrivateRoute>} />
</Routes>
</div>
</div>
</BrowserRouter>
);
export default AppRouter;
useEffect(() => {
if (valid.isAuthenticated) {
navigate("/home");
}
},[valid.isAuthenticated]);
import React from "react";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import PrivateRoute from "./PrivateRoute";
import App from "../components/App";
import Login from "../components/Login";
import HomePage from "../components/HomePage";
import WorkPage from "../components/WorkPage";
const AppRouter = () => {
useEffect(() => {
if (!valid.isAuthenticated) {
navigate("/login");
}
});
return (
<BrowserRouter>
<div>
<NavigationBar />
<div>
{valid.isAuthenticated ? <>
<Routes>
<Route path="/" element={<App />} exact />
<Route path="/home" element={<HomePage />} />
<Route path="/work" element={<WorkPage />} />
</Routes>
</>
:
<>
<Routes>
<Route path="/login" element={<Login />} exact />
</Routes>
</>
}
</div>
</div>
</BrowserRouter>
)
};
export default AppRouter;

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 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

React router history push always route to 404 page

js and facing hard time with react router dom.
I want to change the route when I click a button in my navigation drawer component.
This is my App.js component.
import { Router, Route, Switch } from "react-router-dom";
function App() {
const classes = useStyles();
return (
<Provider store={store}>
<div className={classes.root}>
<NavBar />
<Drawer />
<Router history={history}>
<Switch>
<Route path="/" exact component={Login}></Route>
<Route path="/country" exact component={Country}></Route>
<Route path="/user-create" exact component={User}></Route>
<Route path="/countries" exact component={ListView}></Route>
<Route component={NotFound}></Route>
</Switch>
</Router>
</div>
</Provider>
);
}
And here I pass history prop to the Router component.
History.js
import { createBrowserHistory } from 'history';
export default createBrowserHistory();
Drawer.js
import history from '../../history'
const onRoute = (path) => {
history.push("/user-create");
// props.toggleDrawer();
}
In Drawer.js it is always route to the NotFoundComponet.
Why could this happen?
In your NavBar and Drawer components include the below withRouter or the alt useHistory hook to get access to the history prop.
import { withRouter } from 'react-router'
...
this.props.history.push('/user-create')
...
export default withRouter(...
I'd put <NavBar /> and <Drawer /> inside <Router>, and do
const { push } = useHistory() // from react-router-dom
inside them, to get a reference of the push API

Categories

Resources