async await resolve graphql query promise not resolved - javascript

Hi All i am trying to use graphql api to fetch some country. I am using this API https://studio.apollographql.com/public/countries/home?variant=current and this is playground https://countries.trevorblades.com/
The problem i am facing is that i cannot resolve the Promise. I am using React and fetch method.
my fetchCountries.js file:
import { API_URL } from "./constants";
const COUNTRIES_QUERY = `{
country(code: "BR") {
name
native
emoji
currency
languages {
code
name
}
}
}`;
const fetchCountries = async () => {
await fetch(API_URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
query: COUNTRIES_QUERY,
}),
})
.then((response) => {
if (response.status >= 400) {
throw new Error("Error fetching data");
} else {
return response.json();
}
})
.then((data) => data.data);
};
export default fetchCountries;
i am using async, await in the function so that it gets resolved when i call it. Now in my App.js when i call fetchCountries function in console.log i get :
Promise {<pending>}
[[Prototype]]
:
Promise
[[PromiseState]]
:
"fulfilled"
[[PromiseResult]]
:
undefined
App.js:
import "./App.css";
import fetchCountries from "./api/fetchCountries";
const App = () => {
console.log("CONSOLE LOG API", fetchCountries());
return <div>App</div>;
};
export default App;
I have also tried to use useEffect hook but got the same result:
import "./App.css";
import fetchCountries from "./api/fetchCountries";
import React, { useEffect, useState } from "react";
const App = () => {
const [test, setTest] = useState();
console.log("CONSOLE LOG API", fetchCountries());
useEffect(() => {
const getCountries = async () => {
await fetchCountries();
};
setTest(getCountries());
}, []);
console.log("USE EFFECT API", test);
return <div>App</div>;
};
export default App;

You should do it as follows
const fetchCountries = async () => {
const response = await fetch(API_URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
query: COUNTRIES_QUERY,
}),
})
if (response.status >= 400) {
throw new Error("Error fetching data");
} else {
return await response.json();
}
};
export default fetchCountries;
Or enclose entire fetch.then... chain inside paranthesis.

Related

How can I use axios.defaults.baseURL conditionally? [duplicate]

I am having a config file . where i am setting the baseURL for the entire app and also saving the bearer token for the entire API requests. Here i am in situation to add another api . I dont know how to add another baseURL & use this on my API requests.Here i am sharing the code of what i have done.
BASE URL FILE:
import axios from 'axios';
axios.defaults.baseURL = http://localhost:3000/summary;
const setAuthToken = (token) => {
if (token) {
axios.defaults.headers.common.Authorization = `Bearer ${token}`;
} else {
delete axios.defaults.headers.common.Authorization;
}
};
export default setAuthToken;
API ACTION FILE:
export const login = ({ email, password }) => async (dispatch) => {
const userData = {
username: email,
password,
};
try {
const res = await axios.post('/license-api/auth/login', userData, config);
dispatch({
type: LOGIN_SUCCESS,
payload: res.data.token,
});
} catch (error) {
dispatch({
type: LOGIN_FAIL,
});
}
};
i need to add another url like this in BASE URL FILE
axios.defaults.baseURL = http://localhost:6000/profile
how to add this one and use this in API action file.
Please help me with this.
Thanks in advance
As said you could create two instances of axios and use them as needed:
In you BASE URL file:
import axios from 'axios';
const setAuthToken = (token) => {
if (token) {
axios.defaults.headers.common.Authorization = `Bearer ${token}`;
} else {
delete axios.defaults.headers.common.Authorization;
}
};
const mainAxios = axios.create({
baseURL: 'http://localhost:3000/summary'
});
const profileAxios = axios.create({
baseURL: 'http://localhost:6000/profile'
});
export default setAuthToken;
export { mainAxios, profileAxios };
Then in your API ACTION file:
import { profileAxios } from 'path/to/baseurl';
export const login = ({ email, password }) => async (dispatch) => {
const userData = {
username: email,
password,
};
try {
const res = await profileAxios.post('/license-api/auth/login', userData, config);
dispatch({
type: LOGIN_SUCCESS,
payload: res.data.token,
});
} catch (error) {
dispatch({
type: LOGIN_FAIL,
});
}
};
The above code works well. I don't see where setAuthToken is called so if you don't want to call setAuthToken manually then you might want to do this.
import axios from "axios";
import { config } from "./config";
const pythonAPI = axios.create({
baseURL: config.pythonServerUrl,
});
const nodeApi = axios.create({
baseURL: config.nodeServerUrl,
});
const setToken = () => {
const token = localStorage.getItem("auth_token");
if (token) {
pythonAPI.defaults.headers.common.Authorization = `Basic ${token}`;
} else {
delete pythonAPI.defaults.headers.common.Authorization;
}
};
const pythonApi = {};
pythonApi.get = async (url) => {
setToken();
return pythonAPI.get(url).catch((e) => e.response);
};
pythonApi.post = async (url, data) => {
setToken();
return pythonAPI.post(url, data).catch((e) => e.response);
};
export { pythonApi, nodeApi };

next.js is not returning items on getStaticProps()

I am trying to load items to my next.js page and it will fail:
import {getadminInfo} from '../../dataFetch/adminInfo'
import {addItem} from '../../dataFetch/catalog'
import {useState} from "react"
import { getList } from '../../dataFetch/catalogList'
export async function getStaticProps() {
const adminData = await getadminInfo()
const catlist = await getList()
return {
props: {
catlist,
adminData
}
}
}
export default function Main({allPostsData, adminData, catlist}) {
}
My function is :
export function getList() {
const pageInfo = {
page_size : "10",
page:"1"
}
const url = "http://localhost:8000/api/catalog/list?page_size="+pageInfo.page_size+"&page="+pageInfo.page;
try {
fetch(url, {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(data => {
fData=JSON.parse(JSON.stringify(data.response))
console.log("Returned catalog")
return fData
})
.catch(error => console.log(error))
} catch (err) {
console.log(err)
}
}
The API works and I get the right info back but I cannot load it to the page:
Error: Error serializing .catlist returned from getStaticProps in "/admin/main".
Reason: undefined cannot be serialized as JSON. Please use null or omit this value.
I found the issue. I did not implement the fetch correctly. It should have been async.
The reason I did not get the info is because nothing was returned.

NextJS: TypeError: Cannot read property 'json' of undefined

I've this code into pages folder on my NextJS environment. It gets data calling an external API Rest, and it's working because the console.log(response); line show me by console the Json API response. The problem I've is that I get this error in browser:
TypeError: Cannot read property 'json' of undefined
Corresponding with this line code:
const data = await res.json();
This is the complete file with the code:
import React from "react";
import fetch from "node-fetch";
const getFetch = async (invoicesUrl, params) => {
fetch(invoicesUrl, params)
.then((response) => {
return response.json();
})
.then((response) => {
console.log(response);
})
.catch((err) => {
console.log(err);
});
};
export const getServerSideProps = async () => {
const invoicesUrl = "https://192.168.1.38/accounts/123456";
const params = {
method: "get",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
};
const res = await getFetch(invoicesUrl, params);
const data = await res.json();
console.log("Data Json: ", data);
return { props: { data } };
};
This is the Json API response that I see by console:
{
account: [
{
id: '7051321',
type: 'probe',
status: 'open',
newAccount: [Object],
lastDate: '2020-07-04',
taxExcluded: [Object],
totalRecover: [Object],
documentLinks: []
},
]
}
Any idea how can I solve it?
Thanks in advance.
UPDATE
Here the code working good:
import React from "react";
import fetch from "node-fetch";
const getFetch = async (invoicesUrl, params) => {
return fetch(invoicesUrl, params);
};
export const getServerSideProps = async () => {
const invoicesUrl = "https://192.168.1.38/accounts/123456";
const params = {
method: "get",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
};
try {
const res = await getFetch(invoicesUrl, params);
const data = await res.json();
console.log("Data JSON: ", data);
return { props: { data } };
} catch (error) {
console.log("Data ERROR: ", error);
}
};
There are a couple of things you have to change.
const getFetch = async (invoicesUrl, params) => {
fetch(invoicesUrl, params)
.then((response) => {
return response.json();
})
.then((response) => {
console.log(response);
return response; // 1. Add this line. You need to return the response.
})
.catch((err) => {
console.log(err);
});
};
export const getServerSideProps = async () => {
const invoicesUrl = "https://192.168.1.38/accounts/123456";
const params = {
method: "get",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
};
const data = await getFetch(invoicesUrl, params);
// const data = await res.json(); 2. Remove this you have already converted to JSON by calling .json in getFetch
console.log("Data Json: ", data); // Make sure this prints the data.
return { props: { data } };
};
You have return statement in wrong place.
When the function is expecting a return. You need to return when the statements are executed not inside the promise then function because it is an async callback function which is not sync with the statement inside getFetchfunction. I hope i have made things clear. Below is the code which will any how return something
import React from "react";
import fetch from "node-fetch";
const getFetch = async (invoicesUrl, params) => {
return fetch(invoicesUrl, params);
};
export const getServerSideProps = async () => {
const invoicesUrl = "https://192.168.1.38/accounts/123456";
const params = {
method: "get",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
};
try{
const res = await getFetch(invoicesUrl, params);
console.log("Data Json: ", res);
}catch(error){
console.log("Data Json: ", error);
}
return { props: { res } };
};

Strange in React Native not showing err

I have a strange situation with a React Native app.
The part of the code with problems is this:
const request = async (options) => {
const defaults = {baseURL: 'base URL'}
let token = await AsyncStorage.getItem('token');
console.log('this is logged')
if(token) {
console.log("this is logged")
const headers = {
'TokenAuth': token
}
Object.assign(defaults, headers: headers);
}
console.log('this is NOT logged anymore')
options = Object.assign({}, defaults, options);
};
The idea is that i can't see anywhere the javascript error.
The error is on Object.assign(defaults, headers);
Why i can't see it ?
Thank you.
This is the whole component:
import constants from './../constants/constants';
import axios from 'axios';
import { AsyncStorage } from 'react-native';
import * as Utils from '../configs/utils'
const request = async (options) => {
const defaults = {baseURL: constants.BASE_URL}
let token = await AsyncStorage.getItem('token');
if(token) {
const headers = {'TokenAuth': token}
Object.assign(defaults, {headers: headers});
}
options = Object.assign({}, defaults, options);
return axios(options)
.then(response => {
return response.data
} )
.catch( error => {
if (error.response.status == 401) {
Utils.deleteToken();
}
let errResponse = 'Bad Error'
throw errResponse;
});
};
export function getAllTodos() {
return request({method: 'get',
baseURL: constants.BASE_URL,
url: '/api/items',
})
}

unit-test with HTTP request returns Promise { <pending> }

I am using axios mock adapter to mock HTTP request to test my function. After I defined the behaviour for the function, and then I created an instance of the class to call the function, the result is
**Promise { <pending> }**,
what is the problem? how can I return the value I defined?
Here is my code:
UserService.js
export default class UserService {
getUserInfo = userId => {
const params = {
userId,
};
return axios
.get('https://www.usefortesting.com', {
params: { userId: params },
})
.then(response => response.data.userInfo)
.catch(error => error);
};
}
UserService.test.js
import React from 'react';
import axios from 'axios';
import UserService from './UserService';
import MockAdapter from 'axios-mock-adapter';
describe('testing', () => {
let axiosMock;
const Info = {
userInfo: {
id: '123',
name: 'omg',
},
};
beforeEach(function() {
axiosMock = new MockAdapter(axios);
});
afterEach(() => {
axiosMock.reset();
axiosMock.restore();
});
it('testing', () => {
axiosMock
.onGet('https://www.usefortesting.com', {
params: { userId: 'user_1' },
})
.reply(200, Info);
let userService = new UserService();
let response = userService.getUserInfo('user_1');
console.log(response);
});
});
You need to await for response in your test. Either use callbacks or async/await as shown below.
Your test should be like this:
it('testing', async () => { // notice async here
axiosMock
.onGet('https://www.usefortesting.com', {
params: { userId: 'user_1' },
})
.reply(200, Info);
let userService = new UserService();
let response = await userService.getUserInfo('user_1'); // notice await here
console.log(response);
});
OR
it('testing', () => {
...
userService.getUserInfo('user_1').then(response => {
console.log(response);
});
});
You can check this link on jest docs for more examples.
Also there is error in your getUserInfo() method, in params you are passing an object for userId but you need to pass string or int. What you should do is:
return axios.get('https://www.usefortesting.com', {
params: { userId: params.userId },
})...
OR
return axios.get('https://www.usefortesting.com', {
params,
})...

Categories

Resources