'Getting the response twice from server in react

I am working on a mern app and currently working on the dashboard part of it , now the problem is i am getting some data from my express server but the problem is my server runs only once but when i console log my react code i can see that it se getting data twice , once the object is empty and in the next response i get the whole data, this creating a serious problem because i append that in my redux as soon as i get it from server and when i use that data in another component i get undefined and the code breaks , because it doesn't wait for the second response and throws error on the first one. Now i dont know what type of problem is but here is my code:- Private route code:-

import React, { Component ,useEffect} from 'react';
import { useSelector } from 'react-redux';
import {Navigate, Route , useNavigate} from 'react-router-dom';
import Home from './Home/Home';
import Landing_page from './login_and_reg/Landing_page/Landing_page';
import {useDispatch} from 'react-redux'
import { bindActionCreators } from 'redux';
import {action} from '../state/index'

const Protected_routes = () => {
    const Navigate = useNavigate();
    const auth_check = useSelector(state => state.auth)
    const data_check = useSelector(state => state.data)
    const dispatch = useDispatch();
    const {auth_checking,user_data} = bindActionCreators(action,dispatch)


    const private_routes = async() =>{
        const res = await fetch('/getdata',{
            method:'POST',
            headers:{
                'Content-Type' : 'application/json',
                'x-auth-token':localStorage.getItem('token')
            }
        })
        const data = await res.json();
        if(data.status == 201){
            {auth_checking('true')}
            user_data(data.userdata)
        }
        else{
            {auth_checking('false')}
        }
    }

    useEffect(()=>{
        private_routes()
    },[])

    console.log({auth_check})
    console.log('this is the data i get from express',data_check)
    if (auth_check=='true') {
            return <Home/>  
    } 
    else {
        return <Landing_page/> 
        }        
    
}

export default Protected_routes

    
        useEffect(()=>{
            private_routes()
        },[])
    
        console.log({auth_check})
        console.log('this is the data i get from express',data_check)
        if (auth_check=='true') {
                return <Home/>  
        } 
        else {
            return <Landing_page/> 
            }        
        
    }
    
    export default Protected_routes

here is the photo from console:- enter image description here

server side code:-

const authToken = async(req,res,next)=>{
  try{
    const authHeader = req.headers['x-auth-token']
    const verified = jwt.verify(authHeader, process.env.ACCESS_TOKEN);
    const user_data = await user.find({_id:verified.id})
    const final_data = {first_name:user_data[0].first_name,second_name:user_data[0].second_name,date:user_data[0].date,gender:user_data[0].gender}
    req.user_data = final_data
    
    next();

  }
  catch(err){
    res.status(400).json({message:'not right',status:400});
    console.log(err)
  }
  
}

app.post('/getdata' , authToken,(req,res) =>{
  
  res.status(201).json({message:'authorized',status:201,userdata:req.user_data});
})


Solution 1:[1]

You are under a misconception here.

Your component code will get executed multiple times before you get data from the server.

The first time your component is mounted your code will get executed, this means that your code:

if (auth_check=='true') {
   return <Home/>  
} 
else {
   return <Landing_page/> 
}

gets executed way before you get an answer from your server.

There are multiple ways of fixing this:

  1. you can add a new state that keeps track of if you got an answer to your server const [hasResponse, setHasResponse] = useState(false). And call setHasResponse from inside private_routes.
  2. You can restructure your entire code, make the auth request before loading the React app and load if after you are sure that a user is logged in or not.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Radu Diță