0

I'm working on a Chat Application and i wanted to store the information of the logged user so I used useContext hook for it. Throughout the project I've only used functional components and have made 2 seperate pages for login and signup. The problem I'm facing is that the login component loads perfectly fine but when i try to go to the signup component from login page it goes to /signup for a split second and then stays at /login

I tried everything I could fine on the web but nothing seems to be working so any help would be much appreciated.

here's my context.js :

import React, { createContext, useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";

const ChatContext = createContext()


const ChatProvider=({children})=>{
    const [user,setUser]=useState()
    const [selectedChat,setSelectedChat]=useState()
    const [chats,setChats]=useState([])
    const navigate=useNavigate()
      useEffect(() => {     
        const userInfo= JSON.parse(localStorage.getItem('user'))
         
         if(!userInfo) {
         
            navigate('/')
         }
         setUser(userInfo)
        
         },[navigate]);
    
    return (
        <ChatContext.Provider value ={{user,setUser,selectedChat,setSelectedChat,chats,setChats}}>
            {children}
        </ChatContext.Provider>
    )
}
export {ChatContext, ChatProvider}

this is how my app.js looks like :

import {Routes,Route} from 'react-router-dom'
import Login from './components/login'
import Signup from './components/signup'
import Chat from './components/chat'
import {ChatProvider} from './context/ChatProvider';
import {BrowserRouter as Router} from 'react-router-dom'

import styles from './App.module.css';

function App() {
  return (
    
      <div className={styles.App}>
        <Router>
        <ChatProvider>
           <Routes>
          <Route exact path='/' element={<Login/>}/>
          <Route  path='/signup' element={<Signup/>}/>
         
        </Routes>
        </ChatProvider>
        </Router>
        
     </div>
       
    
  );
}

export default App;

singup component-

import classes from './styles/signup.module.css'
import { useState,useEffect } from 'react'
import { Link } from 'react-router-dom'
import Input from './input';
import axios from 'axios';
import {useNavigate} from 'react-router-dom'

const Signup = () => {
    const navigate=useNavigate()
      
  useEffect(() => {
    const user = JSON.parse(localStorage.getItem("user"));

    if (user) navigate("/chat");
  }, [navigate]);
    const[btn,setBtn]=useState('Sign-Up')
    const[pic,setPic]=useState('')
   
    const[values,setValues]=useState({
        name:"",
        email:"",
        password:"",
        confirmPassword:"",
        picture:""
    })
    const inputs=[{
        id:1,
        name:"name",
        label:"Name",
        type:"text",

        placeholder :"Enter your name here",
        error:"Username must have atleast 3 letters and no special characters other than space",
        required:true,
        //pattern - error will be generated when given input doestn match this pattern
        pattern :`^[a-zA-Z ]*{3,30}$`
    },
    {
        id:2,
        name:"email",
        type:"email",

        label:"Email",
        placeholder :"Enter your email here",
        required:true,
        error:"enter  a valid email address ",
    },
    {
        id:3,
        name:"password",
        type:"password",
        label:" Password",
        placeholder :"Enter your password here",
        error:'password must be atleast eight-character long and contain at least one letter,one number and one special character',
        required:true,
        pattern:`^(?=.*[0-9])(?=.*[a-zA-Z])(?=.*[!@#$%^&*])[a-zA-Z0-9!@#$%^&*]{8,20}$`,
       
    },
    {
        id:4,
        name:"confirmPassword",
        label:"Confirm Password",
        type:"password",
        placeholder :"Re-Enter Password",
        error:"Passwords dont match",
        required:true,
        //to confirm we can again use pattern and here pattern will be the passowrd 
        //we have taken above as input if the two matches -alright but if they dont generate error
        pattern:values.password
    },
    {
        id:5,
        name:"picture",
        type:"file",
        label:"Profile Picture",
        placeholder :"Select a picture",
        accept:"image/*",
        default:'https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_1280.png'
        //pattern - error will be generated when given input doestn match this pattern
       
    }
]
    const onChange=(e)=>{
        setValues({ ...values,[e.target.name]:e.target.value})
       
    }
    const handleSignUp=async(e)=>{
        e.preventDefault()
        console.log(values)
        values.picture=pic
        try{
            const result = await axios.post('http://localhost:6500/signup',values)
            console.log(result)
            //now since registration is successfull, we'll store the credentials of our user locally
            localStorage.setItem('user',JSON.stringify(values))
            //now since we are signed up we'll redirect user to home page
            navigate('/chat')
        }catch(err){
            console.log(err)
        }
       
    }
    return (  <>
    <div className={classes.contain}>
        <div className={classes.signup}>
            <div className={classes.intro}>
                <Link  to='/'>
                    <img src={require('../images/logo.png')} alt="logo" />
                </Link>
             </div>
        <p className={classes.or}>Welcome To Friendly</p>
        <div className={classes.SignUpForm}>
            <form onSubmit={handleSignUp}>
                 {
                 inputs.map((item)=>(
                    <Input key={item.id} value={values[item.name]}  {...item} onChange={onChange}
                        setBtn={setBtn} setPic={setPic}
                    />
                ))
            }
            <button className={classes.btn}>{btn}</button>
            </form>
           
        </div>
        <p className={classes.or}>OR</p>
        <div className={classes.div}>
            <p>Already Registered? </p>
            <Link to='/'> Login </Link>
       
        </div>

    </div>

    </div>
   
       
    </>);
}
 
export default Signup;

login component -

import Input from './input';
import classes from './styles/login.module.css'
import {Link} from 'react-router-dom'
//import { useState } from 'react';
import React, { useState,useEffect} from "react";
import axios from 'axios';
import {useNavigate} from 'react-router-dom'
const Login = () => {
    const navigate=useNavigate()
      
  useEffect(() => {
    const user = JSON.parse(localStorage.getItem("user"));

    if (user) navigate("/chat");
  }, [navigate]);
    const [values,setValues]=useState({
        email:"",
        password:""
    })
    const inputs=[{
        id:1,
        name:"email",
        label:"Email",
        placeholder:"enter your email here",
        type:"email",
        error:"this email doesn't exist",
        required:true

    },{
        id:2,
        name :"password",
        label:"Password",
        placeholder:"enter your password here",
        type:"password",
        error:"wrong password",
        required:true

    }]
   
    const handleLogin=async(e)=>{
        e.preventDefault();
        try{
            const result = await axios.post('http://localhost:6500/login',values)
            //console.log("this is result",result.ans)
            console.log("this is result",result.data)
            console.log(typeof result)
            //now since registration is successfull, we'll store the credentials of our user locally
            localStorage.setItem('user',JSON.stringify(result.data))
            //now since we are signed up we'll redirect user to home page
            navigate('/chat')
        }catch(err){
            console.log(err)
        }
        console.log(values);
    }
   
     const onChange=(e)=>{
        setValues({ ...values,[e.target.name]:e.target.value})
       
    }

    return ( <>
   
    <div className={classes.contain}>
        
    <div className={classes.login}>
        <div className={classes.intro}>
         <Link  to='/'>
               <img src={require('../images/logo.png')} alt="logo" />
                </Link>
        </div>
        <p className={classes.or}>Welcome Back</p>
        <div className={classes.loginForm}>
            <form onSubmit={handleLogin}>
                 {
                 inputs.map((item)=>(
                    <Input key={item.id} value={values[item.name]}  {...item} onChange={onChange}/>
                ))
            }
            <button className={classes.btn}>login</button>
            </form>
           
        </div>
        <p className={classes.or}>OR</p>
        <div className={classes.div}>
            <p>New to Friendly ? </p>
            <Link to='/signup'> Sign Up</Link>
       
        </div>
        
    </div>
    
    </div>
    
    </> );
}
 
export default Login;
ksquare
  • 11
  • 1

1 Answers1

0

When you go to /signup it triggers rerender of ChatProvider because of useNavigate hook:

const navigate = useNavigate();

navigate has a new value now and triggers useEffect inside of which you navigate to the home page:

if (!userInfo) {
  navigate("/");
}

To solve the problem you can omit navigate from the dependency list:

useEffect(() => {
  const userInfo = JSON.parse(localStorage.getItem("user"));

  if (!userInfo) {
    navigate("/");
  }
  setUser(userInfo);
}, []);

Or use a solution from this answer: https://stackoverflow.com/a/71761856/4980215

Ivan Shumilin
  • 1,743
  • 3
  • 13
  • 18