I am making an app using react and ruby-on-rails. My issue is, when I use the commented out if statement (in App.js: line 31) everything works. However, when I try to use if statemen with expression (line 31), browser respond, that neither onLogin and onSignup is not a function.
App.js
import './App.css';
import HomePage from './HomePage'
import Feed from './Feed'
import Login from "./Login";
import Post from "./Post";
import Signup from './Signup';
import { Routes, Route } from "react-router-dom";
import { useState, useEffect } from 'react';
import NavBar from './NavBar';
import SearchUser from './SearchUser'
import UserPage from './UserPage'
function App() {
const [user, setUser] = useState(false) /* log in method */
const [search, setSearch] = useState([])
const [signup, setSignup] = useState(false)
useEffect(() => {
// auto-login
fetch("/me").then((r) => {
if (r.ok) {
r.json().then((user) => {
setUser(user)});
}
});
}, []);
if (!user) return(signup ? <Signup onSignup={setSignup}/> : <Login onLogin={setUser} onSignup={setSignup}/>);
// if (!user) return(<Login onLogin={setUser} />);
return (
<div className="App">
<NavBar user={user} onLogin={setUser} onSearch={setSearch} ></NavBar>
{search.length > 0 && <SearchUser users={search} clearSearch={setSearch}></SearchUser>}
<Routes>
<Route path="/feed" element={<Feed user={user}/>}></Route>
<Route path="/" element={<HomePage user={user} onLogin={setUser}/>}></Route>
<Route path="/signup" element={<Signup />}></Route>
<Route path="/login" element={<Login />}></Route>
<Route path="/posts/:id" element={<Post />}></Route>
<Route path="/users/:id" element={<UserPage userId={user.id} searched = {search} />}></Route>
</Routes>
</div>
);
}
export default App;
Login.js
import logo from './logo.svg';
import { useState } from 'react';
import { Link } from 'react-router-dom';
function Login({onLogin, onSignup}) {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [errors, setErrors] = useState([])
function handleSubmit(e) {
e.preventDefault();
fetch("/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
username,
password,
}),
})
.then((r) => {
if(r.ok) {
setErrors([])
r.json().then((user) => {
onLogin(user)
console.log(`User: ${user.username} with id: ${user.id} has been logged in`)})
}
else {
r.json().then((err)=> setErrors(err.errors))
}
});
}
return(
<div className = "Login">
<header style={{display: "flex", flexDirection: "column", padding: "100px 500px"}}>
<section><img src={logo} style={{height: "50px", width: "50px"}} alt=""></img>Instaclone</section>
<form
onSubmit={handleSubmit}
style={{display: "flex", flexDirection: "column", margin: "50px 50px"}}>
{/* fetch error handlers for login and signup */}
{errors ?
<p>{errors}</p> :
<p></p>}
{/* fetch error handlers for login and signup */}
<label htmlFor="username">Username:</label>
<input
type="text"
id="username"
value={username}
onChange={(e) => setUsername(e.target.value)}>
</input>
<label htmlFor="password">Password:</label>
<input
type="password"
id="password"
value={password}
onChange={(e) => setPassword(e.target.value)}>
</input>
<button type='submit'>login</button>
<button onClick={()=>onSignup(true)}><Link to="/signup">Don't have an account?</Link></button>
</form>
</header>
</div>
);
}
export default Login;
Signup.js
import logo from './logo.svg';
import { useState } from 'react';
import { Link } from 'react-router-dom';
function Signup({onSignup}) {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [passwordConfirmation, setPasswordConfirmation] = useState("");
const [errors, setErrors] = useState([])
function handleSubmit(e) {
e.preventDefault();
fetch("/signup", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
username,
password,
password_confirmation: passwordConfirmation,
}),
})
.then((r) => {
if(r.ok) {
r.json().then((user) => {
onSignup(false)
console.log(`User: ${user.username} has been created`)})
}
else {
r.json().then((err)=> setErrors(err.errors))
}
});
}
return(
<div className = "Signup">
<header style={{display: "flex", flexDirection: "column", padding: "100px 500px"}}>
<section><img src={logo} style={{height: "50px", width: "50px"}} alt=""></img>Instaclone</section>
<form
onSubmit={handleSubmit}
style={{display: "flex", flexDirection: "column", margin: "50px 50px"}}>
{/* fetch error handlers for login and signup */}
{errors.length > 0 ?
errors.map((error, index)=><p key={index}>{error}</p>) :
<p></p>}
{/* fetch error handlers for login and signup */}
<label htmlFor="username">Username:</label>
<input
type="text"
id="username"
value={username}
onChange={(e) => setUsername(e.target.value)}>
</input>
<label htmlFor="password">Password:</label>
<input
type="password"
id="password"
value={password}
onChange={(e) => setPassword(e.target.value)}>
</input>
<label htmlFor="password_confirmation">Confirm Password:</label>
<input
type="password"
id="password_confirmation"
value={passwordConfirmation}
onChange={(e) => setPasswordConfirmation(e.target.value)}>
</input>
<button type='submit'>Signup</button>
<button onClick={()=>onSignup(false)}><Link to="/login">I have an account!</Link></button>
</form>
</header>
</div>
);
}
export default Signup;
I think the problem is an expression that I used. However, I am not sure what might be the case as I am not getting any errors except the ones mentioned.
enter image description here
I tried to use the old statement I was using and surprisingly it works
Related
I am working on firebase authentication. I have made login, logout(on home), home pages. All are working fine. But when I try to login after I have changed something in router or in my code it works perfectly, that is redirects to Home. But when I login after logout, It does not work and reloads the same login page.
Also when isLoggedIn is set true after first try, it reloads login component. When I manually change url to /home then it works fine.
Here is my code.
App js
import Signup from "./Signup";
import Login from "./Login";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from "./Home";
import ProtectedRoutes from "../ProtectedRoutes";
export default function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/">
<Route
path="home"
element={
<ProtectedRoutes
isLoggedIn={JSON.parse(localStorage.getItem("isLoggedIn"))}
>
<Home />
</ProtectedRoutes>
}
/>
<Route path="login" element={<Login />} />
<Route path="signup" element={<Signup />} />
</Route>
</Routes>
</BrowserRouter>
);
}
Login
import React from "react";
import { useRef, useState } from "react";
import { Button, Card, Form, Alert, Container } from "react-bootstrap";
import { signInWithEmailAndPassword } from "firebase/auth";
import { auth } from "../firebaserc";
import { Link, useNavigate } from "react-router-dom";
export default function Login() {
const emailRef = useRef();
const passwordRef = useRef();
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
const navigate = useNavigate();
const handleSubmit = (e) => {
e.preventDefault();
signInWithEmailAndPassword(
auth,
emailRef.current.value,
passwordRef.current.value
)
.then((userCredential) => {
// Signed in
const user = userCredential.user;
// ...
console.log(user);
localStorage.setItem("isLoggedIn", true);
if (JSON.parse(localStorage.getItem("isLoggedIn"))) {
navigate("/home");
}
setError("");
})
.catch((error) => {
setError(error.message);
});
};
return (
<>
<Container
className="d-flex align-items-center justify-content-center"
style={{
minHeight: "100vh",
}}
>
<div
className="w-100"
style={{
maxWidth: "400px",
}}
>
<Card>
<Card.Body>
<h2 className="text-center mb-3">Login</h2>
{error && <Alert variant="danger">{error}</Alert>}
<Form onSubmit={handleSubmit}>
<Form.Group id="email" className="mb-2">
<Form.Label>Email</Form.Label>
<Form.Control type="email" ref={emailRef} required />
</Form.Group>
<Form.Group id="password" className="mb-2">
<Form.Label>Password</Form.Label>
<Form.Control type="password" ref={passwordRef} required />
</Form.Group>
<Button disabled={loading} className="w-100 mt-2" type="submit">
Login
</Button>
</Form>
</Card.Body>
</Card>
<div className="w-100 text-center mt-2">
New here? <Link to="/signup">Signup</Link>
</div>
</div>
</Container>
</>
);
}
Signup
import React from "react";
import { useRef, useState } from "react";
import { Button, Card, Form, Alert, Container } from "react-bootstrap";
import { createUserWithEmailAndPassword } from "firebase/auth";
import { auth } from "../firebaserc";
import { Link, useNavigate } from "react-router-dom";
export default function Signup() {
const emailRef = useRef();
const passwordRef = useRef();
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
const navigate = useNavigate();
const handleSubmit = (e) => {
e.preventDefault();
createUserWithEmailAndPassword(
auth,
emailRef.current.value,
passwordRef.current.value
)
.then((userCredential) => {
// Signed in
const user = userCredential.user;
console.log(user);
setError("");
navigate("/home");
localStorage.setItem("isLoggedIn", true);
// ...
})
.catch((error) => {
setError(error.message);
// ..
});
};
return (
<>
<Container
className="d-flex align-items-center justify-content-center"
style={{
minHeight: "100vh",
}}
>
<div
className="w-100"
style={{
maxWidth: "400px",
}}
>
<Card>
<Card.Body>
<h2 className="text-center mb-3"> Sign Up</h2>
{error && <Alert variant="danger">{error}</Alert>}
<Form onSubmit={handleSubmit}>
<Form.Group id="email" className="mb-2">
<Form.Label>Email</Form.Label>
<Form.Control type="email" ref={emailRef} required />
</Form.Group>
<Form.Group id="password" className="mb-2">
<Form.Label>Password</Form.Label>
<Form.Control type="password" ref={passwordRef} required />
</Form.Group>
<Button disabled={loading} className="w-100 mt-2" type="submit">
Sign Up
</Button>
</Form>
</Card.Body>
</Card>
<div className="w-100 text-center mt-2">
Already have an account <Link to="/login">Login</Link>
</div>
</div>
</Container>
</>
);
}
Home
import React from "react";
import { Button } from "react-bootstrap";
import { auth } from "../firebaserc";
import { signOut } from "firebase/auth";
import { useNavigate } from "react-router-dom";
export default function Home() {
const navigate = useNavigate();
const handleLogout = () => {
signOut(auth)
.then(() => {
// Sign-out successful.
localStorage.removeItem("isLoggedIn");
navigate("/login", { replace: true });
})
.catch((error) => {
// An error happened.
console.log(error.message);
});
};
return (
<div>
Home
<Button onClick={handleLogout}>Logout</Button>
</div>
);
}
Protected Routes
import { Navigate } from "react-router-dom";
const ProtectedRoutes = ({ isLoggedIn, children }) => {
if (!isLoggedIn) {
return <Navigate to="/login" replace />;
}
return children;
};
export default ProtectedRoutes;
Let's say you want to make a React App refresh ,
Simply
React.useEffect(() => {
doSomething();
}, [doSomething, IsAuthenticated ]);
once this values change it will update this component
This value need to be observable
firebase gives you that
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
} else {
// No user is signed in.
}
});
https://firebase.google.com/docs/auth/web/manage-users
and with react you can also make
firebase.auth().onAuthStateChanged((user) => {
if (user) {
handleLogin(user);
} else {
Logout();
}
});
function Logout() {
setAuthintecated(false)
};
Also here some resource for you
https://www.freecodecamp.org/news/react-firebase-authentication-and-crud-operations/
GoodLuck
import React, { useContext } from "react";
import { useLocation } from "react-router";
import { Navigate, Outlet } from "react-router-dom";
function ProtectedRoute({ children }) {
const location = useLocation();
const user = sessionStorage.getItem("userDetails");
console.log(location)
return user? (
children
) : (
<Navigate
to="/login"
replace
state={{
from: location,
}}
/>
);
}
export default ProtectedRoute;
The above code is for the protected route
import React, { useContext, useState } from "react";
import "./login.css";
import Image from "../../assests/images/login-image.jpeg";
import Person from "#mui/icons-material/Person";
import RemoveRedEyeSharp from "#mui/icons-material/RemoveRedEyeSharp";
import VisibilityOffSharp from "#mui/icons-material/VisibilityOffSharp";
import ArrowBackSharp from "#mui/icons-material/ArrowBackSharp";
import { UserDetails } from "../../App";
import { motion } from "framer-motion";
import FormError from "../formError/FormError";
import { HashLoader } from "react-spinners";
import baseUrl from "../../config/BaseUrl";
import axios from "axios";
import { useLocation, useNavigate, Link } from "react-router-dom";
function Login() {
const [showPassword, setShowPassword] = useState(false);
const [showError, setShowError] = useState(false);
const [userDetails, setUserDetails] = useContext(UserDetails);
const location = useLocation();
const navigate = useNavigate();
const [userForm, setUserForm] = useState({
username: "",
password: "",
});
const [message, setMessage] = useState("Default");
const [theme, setTheme] = useState("None");
const [loading, setLoading] = useState(false);
const handleShowPassword = () => {
setShowPassword(!showPassword);
};
const handleChange = (e) => {
const { name, value } = e.target;
setUserForm({ ...userForm, [name]: value });
};
const handleSubmit = async (e) => {
e.preventDefault();
setLoading(true);
try {
const response = await axios.post(`${baseUrl}/user/login`, userForm);
sessionStorage.setItem("userDetails", JSON.stringify(response.data.user));
sessionStorage.setItem("token", JSON.stringify(response.data.token));
setUserDetails(response.data.user);
if(location.state?.from){
navigate(location.state.from)
}
else{
navigate("/")
}
setLoading(false);
} catch ({ response }) {
setMessage(response.data.message);
setTheme("loginError");
setShowError(true);
setLoading(false);
}
};
return (
<motion.div
className="loginBackground"
initial={{ opacity: 0 }}
animate={{
opacity: 1,
transition: {
duration: 0.15,
},
}}
exit={{
opacity: 0,
transition: {
duration: 0.15,
},
}}
>
<div className="loginForm">
{loading && (
<div className="loginLoading">
<HashLoader
color="#002db3"
loading={loading}
size={100}
></HashLoader>
</div>
)}
{!loading && (
<form className="loginFormInputs" onSubmit={handleSubmit}>
<div className="loginBack">
<ArrowBackSharp
style={{ fontSize: "1.7rem", cursor: "pointer" }}
onClick={() => navigate("/")}
></ArrowBackSharp>
</div>
<div className="loginFormHeader">
<div className="loginFormTitle">Welcome Back</div>
<div className="loginFormSubHeading">
Please login to your account to dive deep inside
</div>
</div>
<div className="loginFormInput">
<input
type="text"
name="username"
className="loginInput"
placeholder="Email"
required={true}
value={userForm.username}
onChange={handleChange}
/>
<Person></Person>
</div>
<div className="loginFormInput">
<input
type={showPassword ? "text" : "password"}
name="password"
className="loginInput"
spellCheck={false}
placeholder="Password"
required={true}
value={userForm.password}
onChange={handleChange}
/>
{showPassword ? (
<RemoveRedEyeSharp
onClick={handleShowPassword}
style={{ cursor: "pointer" }}
/>
) : (
<VisibilityOffSharp
onClick={handleShowPassword}
style={{ cursor: "pointer" }}
/>
)}
</div>
<div className="loginFormSubmit">
<button className="loginFormButton" type="submit">
Dive Deep
</button>
</div>
{showError && (
<FormError theme={theme} message={message}></FormError>
)}
<div className="loginFormSignUp">
Don't have an account?{" "}
<Link to={"/register"} style={{textDecoration:"none"}}>
<span
style={{
cursor: "pointer",
color: "blue",
fontWeight: "600",
fontSize: "1.1rem",
}}
>
Signup
</span>
</Link>
</div>
</form>
)}
<img src={Image} alt="img" className="loginImage" />
</div>
</motion.div>
);
}
export default Login;
This is the code snippet for the login component where the handle submit function is handling the redirect. Why is the protected route re-rendering twice? I tried removing the hooks and using session storage but still the protected route rendered twice and I can't understand why
I'm having a problem where my code does not want to work while redirecting to the main page which is Dashboard.js. That file is just an UI I'm working on. I'm currently working on a signup and login page. Here is the code.
Signup.js
import { Form, Button, Card, Alert } from "react-bootstrap"
import { useAuth } from "../contexts/AuthContext"
import { Link, useHistory } from "react-router-dom"
export default function Signup() {
const emailRef = useRef()
const passwordRef = useRef()
const passwordConfirmRef = useRef()
const { signup } = useAuth()
const [error, setError] = useState("")
const [loading, setLoading] = useState(false)
const history = useHistory()
async function handleSubmit(e) {
e.preventDefault()
if (passwordRef.current.value !== passwordConfirmRef.current.value) {
return setError("Passwords do not match")
}
try {
setError("")
setLoading(true)
await signup(emailRef.current.value, passwordRef.current.value)
history.push("/")
} catch {
setError("Failed to create an account")
}
setLoading(false)
}
return (
<>
<Card>
<Card.Body>
<h2 className="text-center mb-4">Sign Up</h2>
{error && <Alert variant="danger">{error}</Alert>}
<Form onSubmit={handleSubmit}>
<Form.Group id="email">
<Form.Label>Email</Form.Label>
<Form.Control type="email" ref={emailRef} required />
</Form.Group>
<Form.Group id="password">
<Form.Label>Password</Form.Label>
<Form.Control type="password" ref={passwordRef} required />
</Form.Group>
<Form.Group id="password-confirm">
<Form.Label>Password Confirmation</Form.Label>
<Form.Control type="password" ref={passwordConfirmRef} required />
</Form.Group>
<Button disabled={loading} className="w-100" type="submit">
Sign Up
</Button>
</Form>
</Card.Body>
</Card>
<div className="w-100 text-center mt-2">
Already have an account? <Link to="/login">Log In</Link>
</div>
</>
)
}
AuthContext.js
import { auth } from "../firebase"
const AuthContext = React.createContext()
export function useAuth() {
return useContext(AuthContext)
}
export function AuthProvider({ children }) {
const [currentUser, setCurrentUser] = useState()
const [loading, setLoading] = useState(true)
function signup(email, password) {
return auth.createUserWithEmailAndPassword(email, password)
}
function login(email, password) {
return auth.signInWithEmailAndPassword(email, password)
}
function logout() {
return auth.signOut()
}
function resetPassword(email) {
return auth.sendPasswordResetEmail(email)
}
function updateEmail(email) {
return currentUser.updateEmail(email)
}
function updatePassword(password) {
return currentUser.updatePassword(password)
}
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged(user => {
setCurrentUser(user)
setLoading(false)
})
return unsubscribe
}, [])
const value = {
currentUser,
login,
signup,
logout,
resetPassword,
updateEmail,
updatePassword
}
return (
<AuthContext.Provider value={value}>
{!loading && children}
</AuthContext.Provider>
)
}
Login.js
import { Form, Button, Card, Alert } from "react-bootstrap"
import { useAuth } from "../contexts/AuthContext"
import { Link, useHistory } from "react-router-dom"
export default function Login() {
const emailRef = useRef()
const passwordRef = useRef()
const { login } = useAuth()
const [error, setError] = useState("")
const [loading, setLoading] = useState(false)
const history = useHistory()
async function handleSubmit(e) {
e.preventDefault()
try {
setError("")
setLoading(true)
await login(emailRef.current.value, passwordRef.current.value)
history.push("/")
} catch {
setError("Failed to log in")
}
setLoading(false)
}
return (
<>
<Card>
<Card.Body>
<h2 className="text-center mb-4">Log In</h2>
{error && <Alert variant="danger">{error}</Alert>}
<Form onSubmit={handleSubmit}>
<Form.Group id="email">
<Form.Label>Email</Form.Label>
<Form.Control type="email" ref={emailRef} required />
</Form.Group>
<Form.Group id="password">
<Form.Label>Password</Form.Label>
<Form.Control type="password" ref={passwordRef} required />
</Form.Group>
<Button disabled={loading} className="w-100" type="submit">
Log In
</Button>
</Form>
<div className="w-100 text-center mt-3">
<Link to="/forgot-password">Forgot Password?</Link>
</div>
</Card.Body>
</Card>
<div className="w-100 text-center mt-2">
Need an account? <Link to="/signup">Sign Up</Link>
</div>
</>
)
}
App.js
import React from "react"
import Signup from "./Signup"
import { Container } from "react-bootstrap"
import { AuthProvider } from "../contexts/AuthContext"
import { BrowserRouter as Router, Switch, Route } from "react-router-dom"
import Dashboard from "./Dashboard"
import Login from "./Login"
import PrivateRoute from "./PrivateRoute"
import ForgotPassword from "./ForgotPassword"
import UpdateProfile from "./UpdateProfile"
function App() {
return (
<Container
className="d-flex align-items-center justify-content-center"
style={{ minHeight: "100vh" }}
>
<div className="w-100" style={{ maxWidth: "400px" }}>
<Router>
<AuthProvider>
<Switch>
<PrivateRoute exact path="/" component={Dashboard} />
<PrivateRoute path="/update-profile" component={UpdateProfile} />
<Route path="/signup" component={Signup} />
<Route path="/login" component={Login} />
<Route path="/forgot-password" component={ForgotPassword} />
</Switch>
</AuthProvider>
</Router>
</div>
</Container>
)
}
export default App
index.js
import ReactDOM from "react-dom"
import App from "./components/App"
import "bootstrap/dist/css/bootstrap.min.css"
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById("root")
)
The problem I'm having in this code is at the useHistory part in Login.js(Line 12 and 21) and Signup.js(Line 13 and 26). Included the other codes because I think that all of the code might be linked to one another.
Thank you.
In both login and signup scenarios you are redirecting to home page immediately after a successful call. However your context value is updating only when the onAuthStateChanged function callback is called by firebase. There can be a small lag during this time and hence you aren't able to redirect to the PrivateRoute correctly.
A reliable way of handling this would be to wait for the currentUser data to be available from context like
const { login, currentUser } = useAuth()
async function handleSubmit(e) {
e.preventDefault()
try {
setError("")
setLoading(true)
await login(emailRef.current.value, passwordRef.current.value)
} catch {
setError("Failed to log in");
}
setLoading(false)
}
useEffect(() => {
if(currentUser) {
history.push('/');
}
}, [currentUser]);
A similar handling can be done in signup component too. This way even if you try to visit the login or signup routes directly from browser url, you will be redirected to home page if the user is already logged in.
I have a react router with 5 pages, and check in 4 of them if I have a user logged in so that whether he is redirected, or displays the component.
It works perfectly for the 3 first pages, but the for the last "/create-channel", it won't work for some reason.
The value of loggedIn is true, and for the first 3 pages, it will valid the condition, but for the last, it seems it always redirect me to the login page.
I also tried doing this (reverse the condition):
{loggedIn ? <CreateChannel/> : <Redirect to="/login"/>}
to
{loggedIn ? <Redirect to="/login"/>: <CreateChannel/>}
but I still was redirected to login page. I have no idea of what is happening. The create-channel page doesn't have any redirection inside.
App.js
import {useEffect, useState} from 'react'
import './App.css';
import axios from 'axios';
/** #jsx jsx */
import { jsx } from '#emotion/core'
// Local
import Footer from './Footer'
import Header from './Header'
import Main from './Main'
import Login from './Login'
import Register from './Register'
import CreateChannel from './CreateChannel'
import { ChannelsContext } from './Contexts/ChannelsContext'
import { UserContext } from './Contexts/UserContext';
import { LoggedInContext } from './Contexts/LoggedInContext';
import { createMuiTheme, ThemeProvider } from '#material-ui/core/styles';
import { makeStyles } from '#material-ui/core/styles';
import CssBaseline from '#material-ui/core/CssBaseline';
import { getCookie } from './utils/cookies';
import {
BrowserRouter as Router,
Switch,
Route,
Redirect,
} from "react-router-dom";
export default () => {
//VARIABLES & HOOKS
const styles = useStyles();
const [username, setUsername] = useState("My Account")
const [channels, setChannels] = useState([{id: 0, name: 'channel 0'}]);
const [drawerMobileVisible, setDrawerMobileVisible] = useState(false)
const [darkMode, setDarkMode] = useState(false)
const [loggedIn, setLoggedIn] = useState(false);
useEffect( () => {
const checkLoggedIn = async () => {
if(typeof getCookie('authorization') === "undefined"){
setLoggedIn(false);
console.log("Not logged in")
}else{
setLoggedIn(true);
console.log("Logged in. Redirecting...")
}
}
checkLoggedIn()
}, [loggedIn])
const darkModeToggleListener = () => {
setDarkMode(!darkMode)
console.log(contextLoggedIn.loggedIn)
}
const drawerToggleListener = () => {
setDrawerMobileVisible(!drawerMobileVisible)
}
const contextLoggedIn = {
loggedIn: loggedIn,
setLoggedInContext: setLoggedIn
}
const contextChannels = {
channels: channels,
setChannelsContext: setChannels
}
const contextUser = {
username: username,
setUserContext: setUsername
}
//RENDER
return (
<ThemeProvider theme={theme}>
<UserContext.Provider value={contextUser}>
<LoggedInContext.Provider value={contextLoggedIn}>
<ChannelsContext.Provider value={contextChannels}>
<CssBaseline />
<Router>
<div className={styles.root}>
<Header
drawerToggleListener={drawerToggleListener}
darkModeToggleListener = {darkModeToggleListener}
/>
<Switch>
<Route path="/login">
{loggedIn ? <Redirect to="/welcome"/> : <Login onUser={setUsername}/>}
</Route>
<Route path="/register">
{loggedIn ? <Redirect to="/welcome"/> : <Register/>}
</Route>
<Route path="/welcome">
{loggedIn ? <Main drawerMobileVisible={drawerMobileVisible} /> : <Redirect to="/login"/>}
</Route>
<Route path="/create-channel">
{loggedIn ? <CreateChannel/> : <Redirect to="/login"/>}
</Route>
<Route path="/">
<Redirect to="/login" />
</Route>
</Switch>
<Footer />
</div>
</Router>
</ChannelsContext.Provider>
</LoggedInContext.Provider>
</UserContext.Provider>
</ThemeProvider>
);
}
EDIT:
CreateChannel.js
import { useContext, useState } from 'react';
/** #jsx jsx */
import { jsx } from '#emotion/core'
// Layout
import { useTheme } from '#material-ui/core/styles';
import Grid from '#material-ui/core/Grid';
import Typography from '#material-ui/core/Typography';
import TextField from '#material-ui/core/TextField';
import Button from '#material-ui/core/Button';
import ForumIcon from '#material-ui/icons/Forum';
import { UserContext } from './Contexts/UserContext'
import axios from 'axios';
/** INSPIRED FROM MUI DOCS https://material-ui.com/components/text-fields/ */
const useStyles = (theme) => ({
root: {
flex: '1 1 auto',
background: theme.palette.background,
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
'& > div': {
marginLeft: 'auto',
marginRight: 'auto',
marginTop: '1%',
marginBottom: '1%',
width: '30%',
},
},
password:{
width:'100%'
},
center:{
width: 'auto',
},
icon:{
width: '100%',
height: '150px'
}
});
export default () => {
const [name, setName] = useState(null)
const [users, setUsers] = useState(null)
const [userNotFound, setUserNotFound] = useState(false)
const contextUser = useContext(UserContext)
const styles = useStyles(useTheme());
const handleCreateChannel = async () => {
//First check if all users exists
let userUnknown = false;
let array = users.split(';')
for(const elem of array){
await axios.get(`http://localhost:3001/users/${elem}`,{}, {withCredentials: true})
.then(function (response){
// eslint-disable-next-line
}).catch(function (error){
if(error.response.status === 404){
userUnknown = true
}
})
}
//Then add yourself
array.push(contextUser.username)
//And finally add to db if all users are known
if(!userUnknown){
await axios.post('http://localhost:3001/channels',{
name: name,
users: array
}, {withCredentials: true}).then(function (response){
window.location.href = '/welcome';
}).catch(function (error){
if(error.response.status === 404){
}
else if(error.response.status === 401){
}
})
}
else{
setUserNotFound(true)
}
}
return (
<div css={styles.root} >
<Grid style={styles.center}>
<ForumIcon
color='primary'
css={styles.icon}
/>
</Grid>
<Grid style={styles.center}>
<Typography variant='h2' color='primary'>
Create a channel
</Typography>
</Grid>
<Grid>
<TextField
variant="outlined"
id="name"
label="Channel name"
name="name"
autoFocus
fullWidth
onChange={(e) => setName(e.target.value)}
/>
</Grid>
<Grid>
<TextField
error = {userNotFound}
variant="outlined"
id="users"
label="Users (separated by a coma ) | BETA"
name="Users"
fullWidth
helperText = {userNotFound ? "At least one user does not exist." : "Do not include yourself (automatically added)."}
onChange={(e) => setUsers(e.target.value)}
/>
</Grid>
<Grid>
<Button
type="submit"
margin = 'normal'
variant="contained"
color="primary"
fullWidth
onClick = {handleCreateChannel}
>
Create
</Button>
</Grid>
</div>
);
}
Hey SoaAlex and welcome to the community,
I think it is because of the hyphen in your path. I wasn't sure that it is possible so I did a search and found this. Could you please verify this and try without a hyphen? You could try:
<Route path="/createChannel">
or
<Route path="/create_channel">
I am getting the boolean output from the axios.reponse but i want to use this reponse to route to another page.
But I am using form to give data so it can't come to the main return.
So,could u please tell where should i write my route statement such that after getting correct username and password i can redirect to new page.
import withRoot from './modules/withRoot';
// --- Post bootstrap -----
import React, { useState } from 'react';
import { makeStyles } from '#material-ui/core/styles';
import Grid from '#material-ui/core/Grid';
import Link from '#material-ui/core/Link';
import { FormGroup, FormControl, ControlLabel } from "react-bootstrap";
import { Field } from 'react-final-form';
import Typography from './modules/components/Typography';
import AppFooter from './modules/views/AppFooter';
import AppAppBar from './modules/views/AppAppBar';
import Axios from 'axios';
import AppForm from './modules/views/AppForm';
import Button from '#material-ui/core/Button';
import { Alert } from 'reactstrap';
import { email, required } from './modules/form/validation';
import RFTextField from './modules/form/RFTextField';
import FormButton from './modules/form/FormButton';
import FormFeedback from './modules/form/FormFeedback';
import TextField from '#material-ui/core/TextField';
import Home from './Home';
import Dashb from './Dashb';
const useStyles = makeStyles((theme) => ({
form: {
marginTop: theme.spacing(6),
},
button: {
marginTop: theme.spacing(3),
marginBottom: theme.spacing(2),
},
feedback: {
marginTop: theme.spacing(2),
},
}));
export default function SignIn() {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [status, setStatus] = useState(true);
const classes = useStyles();
let demo;
function validateForm() {
return username.length > 0 && password.length > 0;
}
function setIncorrect() {
setStatus(false);
}
function setCorrect() {
setStatus(true);
}
async function handleSubmit(event) {
event.preventDefault();
let user = await Axios.get('http://localhost:9000/admin-service/admin/check/' + username + '/' + password).then(
(response) => {
demo = response.data;
}).catch(
(error) => {
console.log(error.response.data);
setIncorrect();
}
)
if (demo == true) {
console.log("####");
return (
<Home />
)
}
else {
console.log("!!!!!");
}
}
return (
<React.Fragment>
<AppAppBar />
<AppForm>
<React.Fragment>
<Typography variant="h3" gutterBottom marked="center" align="center">
Admin Sign In
</Typography>
</React.Fragment>
<form onSubmit={handleSubmit} className={classes.form} noValidate>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
id="username"
label="Username"
name="username"
autoFocus
onChange={e => { setUsername(e.target.value); setCorrect() }}
/>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
autoComplete="current-password"
onChange={e => { setPassword(e.target.value); setCorrect() }}
/>
{(!status) && <Alert severity="error">Incorrect credentials. Please try again</Alert>}
<FormButton
type="submit"
className={classes.button}
disabled={!validateForm()}
size="large"
color="secondary"
fullWidth
>
Sign In
</FormButton>
</form>
<Typography align="center">
<Link underline="always" href="/premium-themes/onepirate/forgot-password/">
Forgot password?
</Link>
</Typography>
</AppForm>
<div>
if {
}
</div>
</React.Fragment>
);
}
I would write it like so:
async function handleSubmit(event) {
event.preventDefault()
let user = await Axios.get(
'http://localhost:9000/admin-service/admin/check/' +
username +
'/' +
password
)
.then(response => {
demo = response.data
if (demo == true) {
console.log('####')
history.push('/')
} else console.log('not true')
})
.catch(error => {
console.log(error.response.data)
setIncorrect()
})
}
instead of returning the component maybe do a history.push() using react-router-dom