The code works well in Postman. But when fetching it in the front-end the response is not working. I can't find the solution. I am new in MERN stack. It gives me error.
product.action.js:7 Uncaught (in promise) AxiosError {message: 'timeout of 1000ms exceeded', name: 'AxiosError', code: 'ECONNABORTED', config: {…}, request: XMLHttpRequest}
The back end code :- router.get("/products/:slug", getProductsBySlug);
exports.getProductsBySlug = (req, res) => {
const { slug } = req.params;
Category.findOne({ slug: slug })
.select("_id")
.exec((error, category) => {
if (error) {
return res.status(400).json({ error });
}
if (category) {
Product.find({ category: category._id }).exec((error, products) => {
if (error) {
return res.status(400).json({ error });
}
res.status(200).json({ products });
});
}
});
};
Front end code: product.action.js
import axiosInstance from "../helpers/axios";
export const getProductsBySlug = (id) => {
return async (dispatch) => {
const res = await axiosInstance.get(`/products/${id}`);
console.log(res);
};
};
`
The above response is occure error.
`
productListPage:
import React, { useEffect } from "react";
import { useDispatch } from "react-redux";
import { getProductsBySlug } from "../../actions";
import Layout from "../../components/Layout";
import { useParams } from "react-router-dom";
const ProductListPage = (props) => {
const dispatch = useDispatch();
const slug = useParams();
useEffect(() => {
console.log(slug);
dispatch(getProductsBySlug(slug));
}, []);
return <Layout>Product List Page</Layout>;
};
export default ProductListPage;
In App.js
function App() {
return (
<div className="App">
<BrowserRouter>
<Routes>
<Route path="/" exact element={<HomePage />} />
<Route path=":slug" element={<ProductListPage />} />
</Routes>
</BrowserRouter>
</div>
);
Tell me the way please.
In your App.js, change the Route declaration to (add the leading /):
<Route path="/:slug" element={<ProductListPage />} />
In your productListPage component, you should deconstruct the property from useParams:
const { slug } = useParams();
Clear the local storage key/value things, should be working.
Related
I am facing an issue my user is always showing null in the backend, I don't know why.
I am following an Udemy course my tutor is saying middleware is responsible for user identification. but the problem is I typed the same code as my tutor is typing but his codes are working fine mine not.
I am using Axios from the front end to make request.
This my controller ==>
export const currentUser = async (req, res) => {
try {
const user = await User.findById(req._id).select("-password").exec();
console.log("CURRENT_USER", user); return res.json({ ok: true });
} catch (err) {
console.log(err);
}
};
This is my middleware ==>
import { expressjwt } from "express-jwt";
export const requireSignIn = expressjwt({ getToken: (req, res) => req.cookies.token, secret: process.env.JWT_SECRET, algorithms: ["HS256"], }) ;
This my front end code where I have been making request ===>
import { useEffect, useState, useContext } from "react";
import axios from "axios";
import { useRouter } from "next/router";
import { SyncOutlined } from "#ant-design/icons";
import UserNav from "../nav/userNav";
import { Context } from "../../context";
const UserRoutes = ({ children }) => {
const { state: { user } } = useContext(Context);
// state
const [ok, setOk] = useState(false);
// router
const router = useRouter();
useEffect(() => {
fetchUser();
}, []);
const fetchUser = async () => {
try {
const { data } = await axios.get("/api/current-user");
console.log(data);
if (data.ok) setOk(true);
} catch (err) {
console.log(err);
setOk(false);
router.push("/login");
}
};
return (
<>
{!ok ? (
<SyncOutlined spin className="d-flex justify-content-center display-1 text-primary p-5" />
) : (
<div className="UserNavSec">
<div className="UserNavCol1">
<div className="UserNavCont"><UserNav/></div
</div>
<div className="UserNavCol2"> {children} </div
</div>
)}
</>
);
};
export default UserRoutes;
This is how I redirect a user depending if he is logged in or not. I am just checking if there is a cookie or not in this example.
import { Route, Redirect } from "react-router-dom";
import cookies from "js-cookies";
export const PrivateRoute = ({ children, ...rest }) => {
const userSignedIn = () => {
return cookies.getItem("jwt");
};
return (
<Route
{...rest}
render={({ location }) =>
userSignedIn() ? (
children
) : (
<Redirect to={{ pathname: "/login", state: { from: location } }} />
)
}
></Route>
);
};
I am trying to improve my code by checking if a user is logged in with my backend.
What is the proper way to check if a user is logged in with react express and JWT ?
Where should I call my api ?
I have been stuck with this problem for a while now...
Thanks
When you logged in then you set a variable auth true in global state and set localstorage.setItem("auth", true) as like. You need to understand about private route and public route and define private route and public route, when you logged in then get auth true then call private route otherwise call public route.In this time you set again global state from localstorage.getItem("auth") because when you reload this page then auth variable true get in localstorage, hope you understand thanks
So this is how I solved my question.
Might not be the best...
import { Route, Redirect } from "react-router-dom";
import { useEffect, useState } from "react";
import { Loading } from "../Loading/Loading";
import axios from "axios";
export const PrivateRoute = ({ children, isAuthenticated, ...rest }) => {
const [isLoading, setIsLoading] = useState(true);
const [isAuth, setIsAuth] = useState(false);
const getIsAuthenticated = async () => {
try {
const res = await axios.get("http://localhost:5000/api/user");
console.log(res);
setIsAuth(true);
} catch (error) {
console.log(error);
setIsAuth(false);
}
setIsLoading(false);
};
useEffect(() => {
getIsAuthenticated();
return () => {};
}, [isAuth]);
if (isLoading) {
return <Loading />;
}
return (
<Route
{...rest}
render={({ location }) =>
isAuth ? (
children
) : (
<Redirect to={{ pathname: "/login", state: { from: location } }} />
)
}
></Route>
);
};
backend code
const user_GET = async (req, res) => {
res.status(400).send("wrong token");
//res.status(200).send("right token");// DEBUG
};
I am trying to make a protected route with Reatjs, nodejs and JWT. The problem is that my component renders before my API checked the client token. This is the code I am trying :
import React, {useState, useEffect} from 'react';
import { Route, Redirect } from 'react-router-dom';
import AuthAPI from './../utils/AuthAPI';
const ProtectedRoute = ({children, ...rest}) => {
const [isAuth, setIsAuth] = useState(false);
const fetchData = async () => {
await AuthAPI.isAuth((res)=>{ //API call
setIsAuth(res);
});
}
useEffect(()=>{
fetchData();
},[]);
return (
<Route {...rest}
render={(props)=>{
return(
isAuth ? children : <Redirect to='/' />
);
}}
/>
);
};
And this is the API call :
static isAuth(callback){ //static method from the class 'AuthAPI' imported above
const url = 'http://localhost:5000/api/Auth/checking';
const options = {
method: 'GET',
url: url,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json;charset=UTF-8',
},
data: {}
}
return axios(options)
.then((response)=>{
callback(true);
}).catch((err)=>{
callback(false);
});
}
When I load the page, it directly redirects since the state isAuth is set to false by default.
I already used this model of code to display a list of things gotten from an API and it worked fine. I assume it is not the best way to do that but most of the examples I have found are not using an actual API but just fake auth without using promises.
EDIT 1.2 :
I've tried this code, from Udendu Abasili :
import React, {useState, useEffect} from 'react';
import { Route, Redirect } from 'react-router-dom';
import AuthAPI from './../utils/AuthAPI';
const ProtectedRoute = ({children, ...rest}) => {
const [isAuth, setIsAuth] = useState(false);
const [isLoaded, setIsLoaded] = useState(false)
useEffect(()=>{
let mounted = true;
AuthAPI.isAuth().then(()=>{
if (mounted) {
console.log("Worked"); //display Worked
setIsLoaded(true); // This line 1
setIsAuth(true); // This line 2
}
}).catch(()=>{
if (mounted) {
console.log("Failed");
setIsLoaded(true);
setIsAuth(false);
}
});
return () => {
mounted = false;
}
},[]);
return (
!isLoaded ?
<h5>Loading</h5> : (
<Route {...rest}
render={(props)=>{
console.log("--->",isAuth,",",isLoaded); // displays false, true
return(
isAuth ? children : <Redirect to='/' />
);
}}
/>
)
);
};
export default ProtectedRoute;
I have found a weird bug. If I swap the lines commented as 'line 1' and 'line 2', it works otherwise it doesn't.
The way react js lifecycle works, the return component gets called before useEffect(which the hook equivalent of componentDidMount on the first mount). So you need to create a form of loader component ( replace the <Text>Loading</Text> with an actual CSS loader ) that waits for your isAuth function to finish.
const ProtectedRoute = ({children, ...rest}) => {
const [isAuth, setIsAuth] = useState(false);
const [loaded, setLoaded] = useState(false);
const fetchData = async () => {
//you need to add try catch here
await AuthAPI.isAuth((res)=>{ //API call
setIsAuth(res);
setLoaded(true)
});
}
useEffect(()=>{
fetchData();
},[]);
return (
loaded ?
<Text>Loading</Text> : (
<Route {...rest}
render={(props)=>{
return(
isAuth ? children : <Redirect to='/' />
);
}}
)
/>
);
};
As you rightfully said, this is not the best way to do it. I won't recommend calling a function to check authentication in the protected route component. Typically, I just pass an isAuthenticated paramter to ProctectedRoute component which gets updated with help of Redux. You should look it up
I am having an issue with a react project im working on
my authHelper is not being imported correctly into a privateRoute component im making. Im a bit of a newb and going off a book I purchased called full stack react projects from Pakkt. I noticed the book has issues all over it with incorrect imports and exports
here is the code below
import { Route, Redirect } from 'react-router-dom';
import auth from '../../helpers/authHelper.js';
const PrivateRoute = ({ component: Component, ...rest }) => {
<Route {...rest} render={props => {
auth.isAuthenticated() ? (
<Component {...props} />
) : (
<Redirect to={{ pathname: '/authentication/card',
state: { from: props.location }}} >
</Redirect>
)
}} />
}
export default PrivateRoute
here is the authHelper
import axios from "axios"
const signout = async () => {
try {
let response = await axios.get('auth/signout', {method: 'GET' })
return await response.json()
} catch (err) {
console.log(err)
}
}
const authenticate = (jwt, cb) => {
if(typeof window !== "undefined")
sessionStorage.setItem('jwt', JSON.stringify(jwt))
cb()
}
const isAuthenticated = () => {
if(typeof window == "undefined")
return false
if (sessionStorage.getItem('jwt'))
return JSON.parse(sessionStorage.getItem('jwt'))
else
return false
}
const clearJWT = (cb) => {
if(typeof window !== "undefined")
sessionStorage.removeitem('jwt')
cb()
signout().then((data) => {
document.cookie = "t=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;"
})
}
export { isAuthenticated, authenticate, clearJWT}
Solved.
in PrivateRoute.js I changed
import auth from '../../helpers/authHelper.js'
to
const auth = require('../../helpers/authHelper.js')
There was also another error in PrivateRoute.js
const PrivateRoute = ({ component: Component, ...rest }) => { //this curly brace needs to be ( instead of {
<Route {...rest} render={props => { this needs to be a ( instead of {
auth.isAuthenticated() ? (
<Component {...props} />
) : (
<Redirect to={{ pathname: '/authentication/card',
state: { from: props.location }}} >
</Redirect>
)
} //this Curley brace to left needs to be a ) instead of } //} />
} // this needs to be changed to a ) instead of }
export default { isAuthenticated, authenticate, clearJWT }
or
export const ()=>{}
And
const PrivateRoute = ({ component: Component, ...rest }) => (
<Route {...rest} render={props => {
auth.isAuthenticated() ? (
<Component {...props} />
) : (
<Redirect to={{ pathname: '/authentication/card',
state: { from: props.location }}} >
</Redirect>
)
}} />
)
Please I would be happy if anyone would help me
I have a problem, I can not use the server-side functions, I call the functions with axios, and execute it in react hooks.
I actually build chat, which is why I use react hook, because I want messages to be updated all the time.
I also use firestore. There I save the messages, and receive them through the server side function.
It's a component of the chat - it's causing me problems, I do not understand why.
The server side functions work great, I tested them in postman, and they worked. The problem is that I can't run them in a function component. I do not know what I'm doing wrong.
The error I get here is in the line chat.users.length> 0?, When I make this comparison I get that chat.users is undefined, but I do not understand why because I initialize it at first, using a server side function , Which gives the necessary information
I'm very confused, and I'm new here on the site, I'm trying to figure out why it has not worked for two whole days
I think I might be confused by syntax, for example using an unnecessary dispatch inside component of the chat
i got this error:
enter image description here
component of the chat
import React, { useEffect, useState } from 'react';
import './style.css';
import { useDispatch, useSelector } from 'react-redux';
import { getRealtimeUsers, updateMessage, getRealtimeConversations } from '../../redux/actions/chatActions';
import { Fragment } from 'react';
const User = (props) => {
const { chat, onClick } = props;
return (
<div onClick={() => onClick(chat)} className="displayName">
<div className="displayPic">
<img src="https://i.pinimg.com/originals/be/ac/96/beac96b8e13d2198fd4bb1d5ef56cdcf.jpg" alt="" />
</div>
<div style={{ display: 'flex', flex: 1, justifyContent: 'space-between', margin: '0 10px' }}>
<span style={{ fontWeight: 500 }}>{chat.firstName} {chat.lastName}</span>
<span className={chat.isOnline ? `onlineStatus` : `onlineStatus off`}></span>
</div>
</div>
);
}
const HomePage = (props) => {
const dispatch = useDispatch();
const user = useSelector(state => state.user.credentials);
const chat = useSelector(state => state.chat);
const [chatStarted, setChatStarted] = useState(false);
const [chatUser, setChatUser] = useState('');
const [message, setMessage] = useState('');
const [userUid, setUserUid] = useState(null);
let unsubscribe;
useEffect(() => {
//unsubscribe = dispatch(getRealtimeUsers(user.handle))
dispatch(getRealtimeUsers());
}, []);
//console.log(user);
//componentWillUnmount
useEffect(() => {
return () => {
//cleanup
//unsubscribe.then(f => f()).catch(error => console.log(error));
unsubscribe.then(f => f()).catch(error => console.log(error));
}
}, []);
//function
const initChat = (chat) => {
setChatStarted(true)
setChatUser(`${chat.firstName} ${chat.lastName}`)
setUserUid(chat.handle);
console.log(chat);
dispatch(getRealtimeConversations({ uid_1: user.handle, uid_2: chat.handle }));
}
const submitMessage = (e) => {
const msgObj = {
user_uid_1: user.handle,
user_uid_2: userUid,
message
}
if (message !== "") {
dispatch(updateMessage(msgObj))
.then(() => {
setMessage('')
});
}
//console.log(msgObj);
}
return (
<Fragment>
<section className="container">
<div className="listOfUsers">
{console.log(chat)}
{
//chat.users != undefined
chat.users.length > 0 ?
chat.users.map(user => {
return (
<User
onClick={initChat}
key={user.handle}
user={user}
/>
);
})
: null
}
</div>
<div className="chatArea">
<div className="chatHeader">
{
chatStarted ? chatUser : ''
}
</div>
<div className="messageSections">
{
chatStarted ?
chat.conversations.map(con =>
<div style={{ textAlign: con.user_uid_1 == user.handle ? 'right' : 'left' }}>
<p className="messageStyle" >{con.message}</p>
</div>)
: null
}
</div>
{
chatStarted ?
<div className="chatControls">
<textarea
value={message}
onChange={(e) => setMessage(e.target.value)}
placeholder="Write Message"
/>
<button onClick={submitMessage}>Send</button>
</div> : null
}
</div>
</section>
</Fragment>
);
}
export default HomePage;
This is the axios:
app.get('/realtimeUsers', FBAuth, getRealtimeUsers );
app.post('/updateMessage', FBAuth, updateMessage);
app.get('/realtimeConversations', FBAuth, getRealtimeConversations);
And this is the server side functions - They work 100% - I checked them many times and they worked.:
const { db } = require('../util/admin');
exports.getRealtimeUsers = (req, res) => {
db.collection("users")
.onSnapshot((querySnapshot) => {
const users = [];
querySnapshot.forEach(function (doc) {
if (doc.data().handle != req.user.handle) {
users.push(doc.data());
}
});
return res.json(users);
});
}
exports.updateMessage = (req, res) => {
db.collection('conversations')
.add({
...req.body,
isView: false,
createdAt: new Date()
})
.then(() => {
return res.json({ message: "Conversations added successfully" });
})
.catch((err) => {
console.error(err);
return res.status(500).json({ error: err.code });
});
}
exports.getRealtimeConversations = (req, res) => {
console.log(JSON.stringify("testing"));
console.log(JSON.stringify(req.query));
console.log(JSON.parse(req.query.user));
console.log(JSON.parse(req.query.user).uid_1);
console.log(JSON.parse(req.query.user).uid_2);
db.collection('conversations')
.where('user_uid_1', 'in', [JSON.parse(req.query.user).uid_1, JSON.parse(req.query.user).uid_2])
.orderBy('createdAt', 'asc')
.onSnapshot((querySnapshot) => {
const conversations = [];
querySnapshot.forEach(doc => {
console.log(JSON.stringify(doc));
if (
(doc.data().user_uid_1 == JSON.parse(req.query.user).uid_1 && doc.data().user_uid_2 == JSON.parse(req.query.user).uid_2)
||
(doc.data().user_uid_1 == JSON.parse(req.query.user).uid_2 && doc.data().user_uid_2 == JSON.parse(req.query.user).uid_1)
) {
conversations.push(doc.data())
}
});
console.log(conversations);
return res.json(conversations);
})
//return res.json([]);
}
this is the actions that used in the client side, here i call to the axios:
import { userConstants } from "../types";
import axios from 'axios';
export const getRealtimeUsers = () => (dispatch) => {
dispatch({ type: `${userConstants.GET_REALTIME_USERS}_REQUEST` });
axios
.get('/realtimeUsers')
.then((res) => {
console.log(res);
dispatch({
type: `${userConstants.GET_REALTIME_USERS}_SUCCESS`,
payload: res.data
});
})
.catch((err) => console.log(err))
}
export const updateMessage = (msgObj) => (dispatch) => {
axios.post('/updateMessage', msgObj)
.then(() => { })
.catch((err) => console.log(err));
}
export const getRealtimeConversations = (user) => (dispatch) => {
//user = { uid_1: "from visualcode", uid_2: "userUid" };
console.log(JSON.stringify(user));
axios.get('/realtimeConversations',
{
params: {
user: JSON.stringify(user)
//uid_1:JSON.stringify("user.handle"),
//uid_2:JSON.stringify("userUid")
}
}
)
.then((res) => {
dispatch({
type: userConstants.GET_REALTIME_MESSAGES,
payload: res.data
});
})
.catch((err) => console.log(err))
}
I am not able to understand your whole code flow, i.e., how the chat.users will be populated before initChat is called.
But still, for your problem, you should always put a check for undefined values while iterating through an array.
<div className="listOfUsers">
{console.log(chat)}
{
//chat.users != undefined
chat && chat.users && chat.users.length > 0 &&
chat.users.map(user => {
return (
<User
onClick={initChat}
key={user.handle}
user={user}
/>
);
})
}
</div>