How do I send response object from my get request to the front end with Express and Axios? - express

I am trying to pull data from MongoDB to populate some timers in this app I'm building. However, I can't seem to send my response to the front end with Axios. Here is my route on the backend:
const express = require('express');
const router = express.Router();
const TimerModel = require('../models/Timer');
router.get('/', async (req, res) => {
try {
const timers = await TimerModel.find({});
console.log('Succesful get req', timers);
res.send(timers);
} catch (err) {
console.log(err.message);
res.status(500).send('Server Error');
}
});
module.exports = router;
My console.log in the try statement prints the correct data but I'm having issues with sending it to the front end. Here is the component:
import React, { useState, useEffect } from 'react';
import Timer from '../Timer/Timer';
import axios from 'axios';
import './Wrapper.css';
function Wrapper() {
//State effects
useEffect(() => {
axios
.get('/')
.then((res) => {
console.log(res);
console.log(res.data);
})
.catch((err) => {
console.log(err);
});
});
const handleChange = (event) => {
setTitle(event.target.value);
};
const addTimer = () => {
const timer = <Timer title={title} key={timers.length} />;
let allTimers = timers.slice();
allTimers.push(timer);
setTimers(allTimers);
setTitle('');
};
return (
//JSX Code
);
}
export default Wrapper;
In the axios call I make, I get this weird object when I run console.log(res) and I get my index.html for the res.data. Why don't I have access to the timers object I made with my backend request? Isn't it being sent when I run the command res.send(timers) in my route?

You need to add your API url in axios request. Currently, axios is taking url of your React website that is why your response have index.html file of React website.
useEffect(() => {
axios
.get('api_url/')
.then((res) => {
console.log(res);
console.log(res.data);
})
.catch((err) => {
console.log(err);
});
});

You can save the result in a state like
`````````````
`````````````
const [time, setTimer] = useState(null)
useEffect(() => {
axios.get('/').then(res => setTimer(res.data)
}, [])
`````````````
`````````````
and then use time vairable where you want

Related

how to get a user by id with a get request to express using react native?

I am trying to render One users info for the profile page in react native using express and axios.
This is the controller responsible for getting a user.
// GET ONE USER BY ID
module.exports.findOneSingleUser = (req, res) => {
User.findOne({ _id: req.params.id })
.then(oneSingleUser => res.json({ user: oneSingleUser }))
.catch(err => res.json({ message: 'Something went wrong', error: err }));
}
this is the code im using to make the axios request to the server and I am able to get all the users in the DB but I want to be able to render one user by id or the token that is stored for login and for login to persist which is working.
const ProfileInfo = (props) => {
const { navigation, route } = props
const authCtx = useContext(AuthContext);
const token= authCtx.token
const [userInfo, setUserInfo] = useState([]);
useEffect(() => {
axios.get(`http://localhost:3000/api/users/`)
.then(res => console.log(res.data))
.catch(err => console.log(err))
}, [])
this is the code in util folder that gets the token from the backend
import axios from 'axios'
import { useNavigation } from '#react-navigation/native';
const BASE_URL = 'http://localhost:3000'
// ! LOGIN FUNCTION
export async function authenticate(email,password ){
const token = await axios.post(BASE_URL + '/api/login',
{
email: email,
password: password,
},{ withCredentials: true }
);
return token;
}
// ! REGISTER NEW USER FUNCTION
export async function createUser(email, password) {
const token = await axios.post(BASE_URL + '/api/register',
{
email: email,
password: password,
},{ withCredentials: true }
);
return token;
}
this is the screen where I have the profile info component being used
import React,{useEffect} from 'react'
import ProfileInfo from '../components/Profile/ProfileInfo';
import Statistics from '../components/Profile/Statistics';
const ProfileScreen = (props) => {
const {navigation} = props
return (
<>
<ProfileInfo navigation={navigation}/>
<Statistics />
</>
)
}
export default ProfileScreen
How do or What do I need to pass into the url of the axios request to get the data for the user that is logged in? thanks in advance.
when I change the server side to
User.findOne({ token: req.params.token})
&
useEffect(() => {
axios.get(`http://localhost:3000/api/users/${token}`)
.then(res => console.log(res.data))
.catch(err => console.log(err))
}, [])
I get a user but it is only the first user in DB not the user that is logged in... not sure how to get the one user that is logged in.

How to clean up React-Native useEffect with axios

Currently I have defined in a functional component a useEffect as below
useEffect(() => {
(async function () {
posts.current = await BlogConsumer.getBlogPosts();
setLoading(false);
})();
return () => {
BlogConsumer.call_controller.abort();
};
}, []);
where this BlogConsumer is defined as below
class BlogConsumer {
static posts = {};
static call_controller = new AbortController();
static async getBlogPosts() {
await axios
.get('https://nice.api', {
signal: this.call_controller.signal,
})
.then(response => {
// treatment for success
})
.catch(error => {
// treatment for erros
});
return this.posts;
}
}
export default BlogConsumer;
The overral ideia is that in the render of the component I'll be calling a static method from my consumer and will retrieve the necessary data. For the pourpuse of not having memory leaks, I have my callback function in my useEffect that will abort my call whenever I unmount the component, but this is not working. React's message of Warning: Can't perform a React state update on an unmounted component. still appears if I enter the component and leave the screen before the API call is finished. I don't know where I am wrong, so I'd like a little help.
Thanks in advance.
You could just cancel the request on unmount. Like this:
export const fetchData = async (signal) => {
try {
const res = await instance.get("/pages/home", {
signal,
});
return res.data;
} catch (error) {
return Promise.reject(error);
}
};
useEffect(() => {
const controller = new AbortController();
fetchData(controller.signal);
return () => {
controller.abort()
};
}, []);

ReactNative: AsyncStorage Problem : I can't retrieve Data the correctly

I am trying to use the AsyncStorage in my Project by Saving the token to the AsyncStorage by using setItem()
Action that response with token
import axios from 'axios';
import {URL, Config} from '../../service/Api';
import AsyncStorage from '#react-native-async-storage/async-storage';
export const checkSmsToLoginUser = value => async dispatch => {
dispatch({type: 'USER_LOGIN_REQUEST'});
try {
const {data} = await axios.post(`${URL}user/checkSMSCode`, value, Config);
console.log(data.token); // it consoles the token
await AsyncStorage.setItem('USER_TOKEN', data.token);
dispatch({type: 'USER_LOGIN_SUCCESS', payload: data?.token});
} catch (error) {
dispatch({type: 'USER_LOGIN_ERROR', payload: error});
}
};
and I dispatch the action in the component, then I try to get the the token from the the AsyncStorage by using getItem
const getData = async () => {
try {
const token = await AsyncStorage.getItem('USER_TOKEN');
return token, JSON.parse(token);
} catch (error) {
return error;
}
};
console.log(getData(), 'token From AsyncStorage');
but when I console the token that comes from the AsyncStorage, I have some sort of unhandled promise
any clue what's the problem or maybe solution?
This might help
function App() {
const getData = async () => {
try {
const token = await AsyncStorage.getItem('USER_TOKEN');
// Log here
console.log(JSON.parse(token), 'token From AsyncStorage');
} catch (error) {
return error;
}
};
useEffect(() => {
getData(); // call here
}, []);
return (
<View>
...
</View>
);
}
You are printing an async function without awaiting for it.
The code is correct, but the console log is not correct:
console.log(getData(), 'token From AsyncStorage'); // missing async logic
Insert the console log inside the getData function, or await for the response.
By Adding the getData() in UseEffect and handling the promise by using then().catch() worked for me
useEffect(() => {
getData()
.then(res => {
console.log(res, 'it worked');
setToken(res);
})
.catch(err => {
setError(err);
console.log(err);
});
}, []);

Mocking axios in Jest returns axios is not defined

I have seen similar questions but they dont actually address what am looking for.
so am using using axios globally in app.js for my vue app like window.axios=require('axios')
then in auth.js i have this
export function login(credentials){
return new Promise((res,rej) => {
axios.post('/api/auth/login', credentials)
.then((response) => {
res(response.data);
})
.catch((err) => {
rej("Wrong email or password");
})
});
}
which works fine on the login page
however in my test script
jest.mock("axios", () => ({
post: jest.fn(() => Promise.resolve({data:{first_name:'James','last_name':'Nwachukwu','token':'abc123'}}))
}));
import axios from 'axios'
import {login} from '../helpers/auth'
it("it logs in when data is passed", async () => {
const email='super#gmail.com'
const password='secret';
const result=await login({email,password});
expect(axios.post).toBeCalledWith('/api/auth/login',{"email": "super#gmail.com", "password": "secret"})
expect(result).toEqual({first_name:'James','last_name':'Nwachukwu','token':'abc123'})
})
shows axios is not defined
but if i change auth.js to
import axios from 'axios'
export function login(credentials){
return new Promise((res,rej) => {
axios.post('/api/auth/login', credentials)
.then((response) => {
res(response.data);
})
.catch((err) => {
rej("Wrong email or password");
})
});
}
test passes. how do i run the test without having to import axios on each vue file
I had the same problem just now. I am also including axios via window.axios = require('axios'); in my app.js.
The solution is to set your axios mock on window.axios in your test. So instead of this (incorrect):
axios = {
post: jest.fn().mockName('axiosPost')
}
const wrapper = mount(Component, {
mocks: {
axios: axios
}
})
When your component code calls axios.whatever it is really calling window.axios.whatever (as I understand it), so you need to mirror that in your test environment:
window.axios = {
post: jest.fn().mockName('axiosPost')
}
const wrapper = mount(Component, {
mocks: {
axios: window.axios
}
})
And in your test:
expect(window.axios.post).toHaveBeenCalled()
The above method works fine until you want to chain then to it. In which case you need to set your mock up like this:
window.axios = {
get: jest.fn(() => {
return {
then: jest.fn(() => 'your faked response')
}
}),
}
You don't need to pass it into the component mock though, you can just mount (or shallowMount) the component as usual

Axios with Auth is not a valid axios instance

I'm trying to set Authorization headers on an axios post request using axios.create(). I have this in a file and when I try to import the function into my React Native component, I get the following error:
axiosWithAuth.default().post is not a function
below is my code for the function:
import axios from 'axios';
import {AsyncStorage} from 'react-native';
// import AsyncStorage from '#react-native-community/async-storage'
async function axiosWithAuth() {
const token = await AsyncStorage.getItem('userToken');
console.log('token from asyncstorage' , token);
return axios.create({headers : {'Content-Type': null, Authorization : token}})
}
export default axiosWithAuth;
and I'm using the function in the following React Native Component:
import axiosWithAuth from '../utils/axiosWithAuth';
const Recipe = (props) => {
const likeIt = () => {
console.log('like pressed');
console.log('props', props.recipe.id);
setLike(!like);
axiosWithAuth().post(`API_URL`,{})
.then(res => console.log('response from post like: ', res.data))
.catch(err => console.log('error in posting like', err.response))
}
return (
<Text>This is the Recipe Component </Text>
)
}
You used async with axiosWithAuth function. It is returning a Promise, not an instance of axios. You have to write it like this
(await axiosWithAuth()).post(`API_URL`,{})
.then(res => console.log('response from post like: ', res.data))
.catch(err => console.log('error in posting like', err.response))
Below is the code that worked. Create a variable and set it = await axiosWithAuth(). Then do a post request off of the variable. Below is the axiosWithAuth function definition:
import axios from 'axios';
import {AsyncStorage} from 'react-native';
async function axiosWithAuth() {
const userToken = await AsyncStorage.getItem('userToken');
console.log('userToken', userToken);
// return axios.create({headers : {'Content-Type': null, Authorization : userToken}})
return axios.create({headers : {Authorization : userToken}})
}
export default axiosWithAuth;
and below is the code that is using the axiosWithAuth function:
import axiosWithAuth from '../utils/axiosWithAuth';
const likeIt = async () => {
await setLike(!like);
console.log('liked?', like);
const axiosAuth = await axiosWithAuth();
console.log('axiosAuth', axiosAuth);
if (!like) {
axiosAuth.post(`https://url`,{})
.then(res => {
console.log('response from post like: ', res.data.message);
})
.catch(err => console.log('error in posting like', err.response))
} else {
axiosAuth.delete(`https://url`)
.then(res => console.log('res from unlike', res))
.catch(err => console.log('err from deleting like', err))
}
}