first request in axios not getting data back - reactjs

Hello I am using axios with react and and I have a problem with the first time requests. Every time my web has a full refresh then it is suppose to make two requests to the server:
to load the web global content
the child should load the current page related content
However, when I refresh the page, since the web global content is loaded in the App.js compontDidMount, then the global content is loaded, however for HomePage.js which in this case is the child component to App.js send the request in compontDidMount but checking the server logs, only the option handshake request is received and not the actual get request to get the page related content, however since am using react-router-dom's Link to navigate. If I navigate to another page then come back to home page then I get all the content since in that case the App.js compontDidMount will not be executed. could anyone help or explain why this is happening please
my hoempage.js componentDidMount
looks like this
axios.defaults.xsrfCookieName="csrftoken"
axios.defaults.headers = get_headers()
axios.get(`${API_URL}/dns/`).then(res=>{
this.setState({
top6:res.data.top,
latest:res.data.latest
})
})
my App.js componentDidMount is calling a functions in another file that uppdates redux and looks like this
componentDidMount() {
this.props.loadGlobal();
}
loadGlobal looks like this
export const getGlobal = () => {
return dispatch => {
dispatch(getGlobalStart());
axios.defaults.xsrfCookieName = "csrftoken";
axios.defaults.headers = get_headers();
axios.get(`${API_URL}/api/get-global/`)
.then(res => dispatch(getGlobalSuccess(res.data)))
.catch(err => {
console.log(err.message)
dispatch(getGlobalFail(err.response.data))
}).catch(err=>{
dispatch(setAlert({ "show": true, error: true, "message":"network error fetching data, check your internet and try again or contact side admin if your network is fine"}))
});
};
};
my get_headers() looks like this
function get_headers() {
var headers = {
"Content-Type": "application/json",
};
if (localStorage.getItem('token')) {
headers = {
"Content-Type": "application/json",
"Authorization": `Token ${localStorage.getItem('token')}`,
};
}
return headers
}
i my backend am using django which fetching data from postman or even visiting the url works just fine for me

Related

Axios API call returns a 404 on page render, but still returns api objects in terminal

I am using axios to make an api call to an api found on Apihub for a next JS app.
here is the code for the function to make the call to provide a list of property JSON objects.
export const baseUrl = "https://zillow56.p.rapidapi.com"
export const fetchApiListsingsCustom = async (url) => {
const { data } = await axios.get((url), {
method: 'GET',
headers: {
'X-RapidAPI-Key': '328713ab01msh862a3ad609011efp17e6b4jsn0e7112d5ee9a',
'X-RapidAPI-Host': 'zillow56.p.rapidapi.com'
}
});
data.then((res) => {
console.log(res);
})
.catch((error) => {
console.error(error);
});
return data.json();
}
When rendering the page I'm attempting to inject the response's data to dynamically create a list of apartment listings.
I'm trying to use getServerSideProps so that the data is already available by the time a user requests the page. After fetching the data, I want to also print them in the terminal to validate it's success.
export default function Home({ propertiesCustomdata })
export async function getServerSideProps() {
const propertiesCustom = await fetchApiListsingsCustom(`${baseUrl}`)
const propertiesCustomdata = propertiesCustom.json()
return {
props: {
propertiesCustomdata
}
}
}
The problem is, I seem to be getting a 404 error from the axios call, before the page gets a chance to load. When I access this I get a 404 error but I also manage to receive some contents of the call the API was to make.
My apologies if this is unclear, but this is all I know to report on this so far.
Studying async and await, fetch, and axios. Very confusing.

NextJS - request with large JSON object

I do have a NextJS application where I make a request to the api route using fetch
const options = {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify(filesForImport),
};
const response = await fetch("api/import", options);
quite straightforward.
The catch here, is that the body is a "large" JSON object, with about 6500 lines (as per Postman).
This makes the request to completely hang, I don't see the api/import route to be called at all, and if I check the developer tools/Network I do see the request pending, and never resolves.
If I send a small json with 20 lines, all works as needed, so is defenetelly something with NextJS handling large JSON objects.
I did try to change the config for that route
export const config = {
api: {
bodyParser: false,
},
};
but it doesn't help.
For testing sake, the route doesn't do any logic, commented it all.
export default async (req: NextApiRequest, res: NextApiResponse) => {
console.log(99999)
try {
const files: LocalizationImportData[] = req.body;
console.log(888, files)
//await some logic here, which is commented
res.status(200).end();
} catch (err: unknown) {
if (err instanceof Error) console.error(`failed to import records: ${err.stack}`);
res.status(500).send(err);
}
};
in the case of small payloads, I do see the 99999 in the console, with large requests nothing happens.
I tried to make the requests via Postman, from Edge and Chrome browsers, all behave the same, the request just hangs forever.
The overall file size of that JSON payload is about 200kb, pretty small I'd say.
What else can be changed here?

Why am I getting empty array in fetch request to MongoDB from ReactJS?

I am trying to fetch all the articles from a document in MongoDB in React. It is perfectly working in Backend with NodeJS when I tested with Postman. But in Frontend , React, I am getting empty array. How to solve this.
Server.js (Backend)
app.get('/api/articles', async (req, res)=>{
const client = await MongoClient.connect('mongodb://localhost:27017', {useNewUrlParser:true, useUnifiedTopology:true})
const db = client.db('my-blog')
const articleInfo= await db.collection('articles').find({}).toArray(function(err, result){
if (err) console.log(err)
res.status(200).send(result)
client.close()
})
})
articlePage.js (FrontEnd)
componentDidMount(){
const requestOptions = {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
};
const fetchdata = fetch('/api/articles/').then(res=>res.json())
.then(data=>this.setState({articles:data}))
console.log(this.state.articles)
}
Api address is set up in package.json with proxy:http://localhost:8000
How to get the documents data from MongoDB in React?
Firstly, check if you the API call went through to the server from your React app. If it has, then check for the response code in the network. In your case, 200 is where you get the desired result from the API. If you are not getting the desired result, then check your collection and document names and also arguments your are passing in the query.
As setState is not synchronized, you have to access it in the callback.
this.setState({ articles: data }, () => {
console.log(this.state.articles)
})

Fetch request to Cloudinary API from with React Component fails

I want to make an HTTP request to the Cloudinary API for pictures in my account. The url necessary looks like this:
https://<<API KEY>>:<<API SECRET>>#api.cloudinary.com/v1_1/<<RESOURCE NAME>>/resources/image
and when I hit this url from the browser, I get what I'm looking for, a beautiful JSON object with all my pictures.
But when I hit the url from within a React component,
componentDidMount() {
this.props.fetchArt();
}
I get the following error:
TypeError: Failed to execute 'fetch' on 'Window': Request
cannot be constructed from a URL that includes credentials:
The action creator looks like
export function fetchArt() {
const url = 'https://'+CLOUDINARY_KEY+':'+CLOUDINARY_SECRET+'#api.cloudinary.com/v1_1/prints20/resources/image';
const request = fetch(url).then(res => res.json())
return {
type: FETCH_ART,
payload: request
}
}
Link to the repo: https://github.com/PantherHawk/prints20-2018
Thanks a million in advance!
If your endpoint requires some sort of authorization you'll need to pass that info inside the headers of your request.
Cloudinary Authentication is done using Basic Authentication over secure HTTP. Your Cloudinary API Key and API Secret are used for the authentication.
fetch('https://api.cloudinary.com/v1_1/CLOUD_NAME/resources/image', {
method: 'get',
headers: {
'Authorization': 'Basic ' + base64.encode(API_KEY + ":" + API_SECRET),
},
}).then(res => res.json())

React Relay Modern redirecting to another page when receiving 401 error on network environment

I´m using JWT authentication inside my ReactJS RelayJS network environment. All the token retrieval and processing in server and client are fine. I´m using react router v4 for routing.
My problem is when I receive a Unauthorized message from server (status code 401). This happens if the user points to an application page after the token has expired, ie. What I need to do is to redirect to login page. This is the code I wish I could have:
import { Environment, Network, RecordSource, Store } from 'relay-runtime';
const SERVER = 'http://localhost:3000/graphql';
const source = new RecordSource();
const store = new Store(source);
function fetchQuery(operation, variables, cacheConfig, uploadables) {
const token = localStorage.getItem('jwtToken');
return fetch(SERVER, {
method: 'POST',
headers: {
Authorization: 'Bearer ' + token,
Accept: 'application/json',
'Content-type': 'application/json'
},
body: JSON.stringify({
query: operation.text, // GraphQL text from input
variables
})
})
.then(response => {
// If not authorized, then move to default route
if (response.status === 401)
this.props.history.push('/login') <<=== THIS IS NOT POSSIBLE AS THERE IS NO this.history.push CONTEXT AT THIS POINT
else return response.json();
})
.catch(error => {
throw new Error(
'(environment): Error while fetching server data. Error: ' + error
);
});
}
const network = Network.create(fetchQuery);
const handlerProvider = null;
const environment = new Environment({
handlerProvider, // Can omit.
network,
store
});
export default environment;
Naturally calling this.props.history.push is not possible as the network environment is not a ReactJS component and therefore has no properties associated.
I´ve tried to throw an error at this point, like:
if (response.status === 401)
throw new Error('Unauthorized');
but I saw the error on the browser console, and this cannot be treated properly in the code.
All I wanna do is to redirect to login page in case of 401 error received, but I can´t find a proper way of doing it.
I am not using relay but a render prop. I experienced kind of the same issue. I was able to solve it using the window object.
if (response.statusText === "Unauthorized") {
window.location = `${window.location.protocol}//${window.location.host}/login`;
} else {
return response.json();
}
You can go with useEnvironment custom hook.
export const useEnvironment = () => {
const history = useHistory(); // <--- Any hook using context works here
const fetchQuery = (operation, variables) => {
return fetch(".../graphql", {...})
.then(response => {
//...
// history.push('/login');
//...
})
.catch(...);
};
return new Environment({
network: Network.create(fetchQuery),
store: new Store(new RecordSource())
});
};
// ... later in the code
const environment = useEnvironment();
Or you can create HOC or render-prop component if you are using class-components.
btw: this way you can also avoid usage of the localStorage which is slowing down performance.

Resources