React hitting api multiple times when usestate changes - node.js

import React, { useState, useEffect } from "react";
import Axios from "axios";import { Link, Navigate } from "react-router-dom";
import "../assets/css/login.css";import "react-toastify/dist/ReactToastify.css";
import API from "../backend";
const Signout = () => {const [values, setValues] = useState({reDirect: false,});
const { reDirect } = values;
if (typeof window !== "undefined") {localStorage.removeItem("TWjwt");
const axiosGetCall = async () => {
try {
const res = await Axios.get(`${API}/logout`);
// enter you logic when the fetch is successful
console.log(`data here: `, res);
setValues({ ...values, reDirect: true });
} catch (error) {
// enter your logic for when there is an error (ex. error toast)
console.log(`error log: `, error);
}
};
axiosGetCall();
}
return <>{reDirect === true ? <Navigate to="/" /> : <></>}</>;};
export default Signout;`
hello,
i'm trying to learn react and above code has no problem instead the code is hitting my backend api multiple times for single logout..
i have removed <React.StrictMode> but still it is hitting apis multiple times..
i have understood that when my state changes the code is running again and again..
so any solutions ?

useEffect(() => {
const axiosGetCall = async () => {
const res = await Axios.get(`${API}/logout`);
// enter you logic when the fetch is successful
console.log(`data here: `, res);
if (typeof window !== "undefined") {
localStorage.removeItem("TWjwt");
}
setValues({ ...values, reDirect: true });
};
axiosGetCall();
}, []);
OK- Issue was Solved...

Related

useEffect hook does not update useState flag, flag always remain null when it is used

Hi I am trying to create an authentication app. To do that I create login page and DashBoardPage.
Here is my login code. In My login page code, handleSubmit and submit works correctly, and setAuthenticated, localStorage.setItem("authenticated", true) set true correctly.
function Login() {
useEffect(() => {
localStorage.setItem("authenticated", false)
setAuthenticated(false)
}, []);
//const navigate = useNavigate();
const [email, setEmail] = useState("");
const [password, setPassword] = useState("")
const [authenticated, setAuthenticated] = useState(localStorage.getItem("authenticated") || false)
const handleSubmit = async () =>{
try{
let res = await api.post("/login", {"email": email, "password":password} )
return res
}catch(e){
console.log("Something Went Wrong")
}
}
const submit = (e) =>{
if(!email.match(validEmailRegex)){
console.log("Not Valid Mail Address")
}
handleSubmit()
.then(res => {
console.log(res.data.token)
console.log(res.data.message)
setAuthenticated(true) // It shows that it is authenticated
localStorage.setItem("authenticated", true)
})
.catch(error => console.log(error))
}
After I entered true values in login page, I go to "/DashBoardPage" via using inspector panel.
Here is my DashBoard code
import { useEffect, useState } from "react";
import { Redirect } from "react-router-dom";
const Dashboard = () => {
const [authenticated, setAuthenticated] = useState(null);
useEffect(() => {
console.log("Use Effect First Entered",localStorage.getItem("authenticated"))
const loggedInUser = localStorage.getItem("authenticated");
console.log("Logged in user ", loggedInUser)
if (loggedInUser) {
setAuthenticated(true);
}
else {
setAuthenticated(false)
}
}, []);
console.log("const Dashboard Entered",localStorage.getItem("authenticated"))
console.log("EXIT")
console.log("One Before Return", authenticated)
if (!authenticated) {
return <Redirect replace to="/TestPage" />;
}
if(authenticated) {
return (
<Redirect replace to="/MyProfilePage" />
);
}
};
export default Dashboard;
My problem here is authenticated blocks always remain null, even though I am trying to change their value in useEffect before rendering. As a reason for that, I cannot goto MyProfile page and always go back to TestPage. Can someone explain why it is happening?
Function in the useEffect is executed after render phase of the component. So redirect is happening before useEffect.
Add if (authenticated === null) return null; just before the rest of your ifs
Additional note: setXXX functions from useState hook are not updating the XXX vairable immediately, in-place. The variable will be updated on next render only.

why i cant get an axios response in react?

so I'm having a problem getting data from my server to my front-end using axios.
as you can see in this picture I'm getting a response for the GET method for users/users.
this is my showUsers function
const showUsers = async (req, res) => {
await User.find({})
.then((user) => {
res.status(200).json(user);
})
.catch((error) => {
res.status(400).send(error);
});
};
this is my axios api export
import axios from "axios";
export default axios.create({
baseUrl: "http://localhost:8080/users",
});
and this is my useEffect
import api from "../api/users";
import { useState, useEffect } from "react";
export const LogIn = (props) => {
const { setIsNewMember } = props;
const [users, setUsers] = useState([]);
useEffect(() => {
const fetchUsers = async () => {
try {
const response = await api.get("/users");
setUsers(response.data);
} catch (err) {
if (err.response) {
console.log(err.response.data);
console.log(err.response.status);
console.log(err.response.headers);
} else {
console.log(`Error: ${err.message}`);
}
}
};
fetchUsers();
}, []);
I'm getting this error on the frontend
so although I'm getting it from the postman and other services I'm not getting it on the front.
any idea why is that happening?

`useEffect` not being able to fetch data on component mount

I am trying to set an array of objects into dineIns after fetching them inside useEffect. What I understood is that there is some kind of delay in receiving the data because the state variable returns an empty array when I log it after fetching the data.
import axios from 'axios';
import React, { useEffect, useState } from 'react';
import { useNavigate } from 'react-router';
import jwtDecode from 'jwt-decode';
function CheckIns() {
const [dineIns, setDineIns] = useState([]);
const navigate = useNavigate();
useEffect(() => {
const token = localStorage.getItem('token');
if (token) {
const user = jwtDecode(token);
if (!user) {
localStorage.removeItem('token');
navigate('/login');
} else {
async function UserData(user_email) {
const user_data = await axios
.get(`/api/users/${user_email}`)
.then((res) => {
const info = res.data.reservations;
setDineIns(info);
console.log(dineIns);
});
}
UserData(user.email);
}
} else {
navigate('/login');
}
}, []);
}
What needs to be corrected here to set the state in time?
set state is an async operation, which log the data after set it, will log the old value.
To ensure that the data set correctly, you can use setState again
const info = res.data.reservations
setDineIns(info)
setDineIns(prev => {
console.log(prev)
return prev;
})
Or you can use effect with dineIns dependence.
I think your code works fine.
You are expecting a Promise from the axios call but you are awaiting it.
Try to change your code like this:
useEffect(() => {
const token = localStorage.getItem('token');
if (token) {
const user = jwtDecode(token);
if (!user) {
localStorage.removeItem('token');
navigate('/login');
} else {
async function UserData(user_email) {
try {
const { data } = await axios.get(`/api/users/${user_email}`);
setDineIns(data.reservations);
console.log(dineIns);
} catch (err) {
console.log(err);
}
}
UserData(user.email);
}
} else {
navigate('/login');
}
}, []);

Cannot GET /post/api/posts/5c804ec6ad029f21201c686e Not found, because of unwanted appending of word "posts"

whenever I try to get the post api , I am getting error saying Cannot GET /posts/api/posts/5c804ec6ad029f21201c686e
I am not able to figure out where the "posts" word is getting appended in my api call with axios. I checked my code thourouly but I am not able to catch the bug. Can anyone please help me with this.
Post.js ;-
import React, { Fragment, useEffect } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux';
import Spinner from '../layout/Spinner';
import { getPost } from '../../actions/post';
import PostItem from '../posts/PostItem';
const Post = ({ getPost, post: { post, loading }, match }) => {
useEffect(() => {
getPost(match.params.id)
}, [getPost]);
return <h1>Post</h1>
// loading || post === null ? <Spinner /> :
// <Fragment>
// <PostItem post={post} showActions={false} />
// </Fragment>
}
Post.propTypes = {
getPost: PropTypes.func.isRequired,
post: PropTypes.object.isRequired,
}
const mapStateToProps = state => ({
post: state.post
})
export default connect(mapStateToProps, { getPost })(Post)
Post actions :-
import axios from "axios";
import { setAlert } from './alert';
import {
GET_POSTS,
POST_ERROR,
UPDATE_LIKES,
DELETE_POST,
ADD_POST,
GET_POST
} from './types';
// Get post
export const getPost = id => async dispatch => {
try {
const res = await axios.get(`api/posts/${id}`);
dispatch({
type: GET_POST,
payload: res.data
})
} catch (err) {
dispatch({
type: POST_ERROR,
payload: { msg: err.response.statusText, status: err.response.status }
})
}
}
beckend code in Node.js
//#route Get api/posts/:id
//#desc GET Post by Id
//#access Private
router.get("/:id", auth, async (req, res) => {
try {
const post = await Post.findById(req.params.id);
if (!post) {
return res.status(404).json({ msg: 'Post not found' })
}
res.json(post);
} catch (err) {
console.log(err.message);
if (err.kind === 'ObjectId') {
return res.status(404).json({ msg: 'Post not found' })
}
res.status(500).send('Server Error');
}
});
My immediate thought is that the api call happens on a page other than root, in this case in /posts page (aka http://your-site.com/posts)
By adding a forward slash in front of you call will force your api request go from the root.
Try
await axios.get(`/api/posts/${id}`);

Data leak due to using asynchronous function

I am getting a data leak while using an asychronous function causing my application to not load the second page during navigation.
I am using async/await on my get request, and I have tried to use a cleanup function to prevent this leak, but it is not working.
How do I fix this leak, and still get the data to load when the page is loaded?
import React, { useEffect, useState, useContext } from "react";
import ReactTable from "react-table";
import "react-table/react-table.css";
import axios from "axios";
import StatusContext from "../../context/status/statusContext";
const Table = props => {
const [tableData, setTableData] = useState([]);
const statusContext = useContext(StatusContext);
useEffect(async () => {
await axios
.get("/api/status")
.then(function(response) {
console.log(response.data);
setTableData(
response.data.filter(item => {
let itemDate = new Date(item.date);
let variableDate = new Date() - 604800000;
return itemDate > variableDate;
})
);
})
.catch(function(error) {
console.log(error);
});
}, [statusContext]);
const columns = [
{
id: "Name",
Header: "Name",
accessor: "name"
},
{
Header: "Date",
accessor: "date"
},
{
Header: "Comment",
accessor: "comment"
}
];
return (
<ReactTable
data={tableData}
columns={columns}
pivotBy={["date"]}
defaultPageSize={7}
minRows={5}
/>
);
};
export default Table;
There's really no need to bring async/await into this situation, and in fact useEffect won't work if you do. The only thing you can return from useEffect is a cleanup function, and an async function returns a Promise.
This should work just fine, including a cleanup function in case you unmount your component before the promise resolves:
useEffect(() => {
let isMounted = true;
axios
.get("/api/status")
.then(function(response) {
if (!isMounted) {
return;
}
console.log(response.data);
setTableData(
response.data.filter(item => {
let itemDate = new Date(item.date);
let variableDate = new Date() - 604800000;
return itemDate > variableDate;
})
);
})
.catch(function(error) {
console.log(error);
});
return () => {
isMounted = false;
}
}, [statusContext]);

Resources