Access data outside of Axios await get? - async-await

New to Axios, Vue, NuxtJS.
Most examples I've seen show either .get or await, but not both together. This code was pulled from several using Nuxt JS with headless CMS tutorials and is working, but now I can't seem to figure out how to access the data in other functions outside of the async call.
import axios from 'axios'
export default {
async asyncData ({env, params}) {
const {data} = await axios.get(`${env.cockpit.apiUrl}/collections/get/cat_ruleset?token=${env.cockpit.apiToken}&simple=1`);
return {catrules:data}
}
}

export const addmore = async () => {
const response = await axios.get(`https://jsonplaceholder.typicode.com/users/1`);
return response.data;
}

Related

fetch weatherapi.com with async await react hooks

Can anyone help me why my code doesn't work to fetch API?
I have to build a weather app from several components, must build it structured.
My plan is to have one service component that I have API service in there. then I have to make 3 more components, search component to handle the city search, weatherToday component to show today weather, and weatherForecast component to show five days forecast.
And I have to fetch the API with async an await. Here is the code that I tried(just now I have the code in my App.js just to try if my fetch work)
import { useState, useEffect } from "react";
function App() {
const [data, setData] = useState();
const fetchData = async () => {
await fetch(
`http://api.weatherapi.com/v1/forecast.json?key=1d172d3904e246849d3183628230802&q=Stockholm&days=6&aqi=no&alerts=no`
)
.then((response) => {
return response.json();
})
.then((data) => {
setData(data);
});
};
useEffect(() => {
fetchData();
}, []);
return (
<>
<h3>{data.location.name}</h3>
<p>{data.current.temp_c}</p>
<p>{data.location.localtime}</p>
</>
);
}
export default App;
First of all, welcome to React and StackOverflow!
There's a few issues here:
The main issue is CORS. You can't call this API from your browser - it's meant to be called from a server (backend). I highly recommend using Next.js since you like React, it uses that as it's framework - but it allows you to have Server Components, essentially an Express backend, so that you can perform this API call - then retrieve that data using this client component just to display the data (not to fetch it).
Another issue (but not the problem here) is reusing the data variable in the local scope of then((data) => is not good when you have data defined higher up in the component scope for your state. Use then((d) => instead.
I created a Next.js 13 sandbox for you with this working API call to get you started:
https://codesandbox.io/p/sandbox/broken-field-4nsp1p
In Next.js 13, you can use the app folder, where every component is a Server Component by default. Then you can create Client Component, like the one you have above - you simply have to add use client to the very top of the file, that's it.
Since Next.js 13 is very new (the app folder and concept of Server Components very new and bound to change), you would want to potentially just stick with the pages folder.
In there, you'll see the client component which calls the api folder's getWeather API call.
Finally, you shared your private key with the public. You need to destroy and regenerate that key now:
From the WeatherAPI.com Docs:
Authentication
API access to the data is protected by an API key. If at anytime, you
find the API key has become vulnerable, please regenerate the key
using Regenerate button next to the API key.
https://www.weatherapi.com/docs/
If don't want to use Next.js - then you'll need to use some sort of backend, like Firebase Functions or Google Cloud Functions, etc. Next.js is probably the easiest thing to adapt if you like React though!
Learn about Next.js 13 & /app folder:
https://beta.nextjs.org/docs/getting-started
Learn about Next.js 12 & /pages folder:
https://nextjs.org/docs
Implementing Fetch via Next.js 13
app/head.tsx
export default function Head() {
return (
<>
<title>Weather App</title>
<meta content="width=device-width, initial-scale=1" name="viewport" />
</>
);
}
app.layout.tsx
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
{/*
<head /> will contain the components returned by the nearest parent
head.tsx. Find out more at https://beta.nextjs.org/docs/api-reference/file-conventions/head
*/}
<head />
<body>{children}</body>
</html>
);
}
app/page.tsx
const App = async () => {
console.log("App.js");
const results = await fetch(
`http://api.weatherapi.com/v1/forecast.json?key=1d172d3904e246849d3183628230802&q=Stockholm&days=6&aqi=no&alerts=no`
);
const json = await results.json();
console.log("json", json);
return (
<>
<h3>{json.location.name}</h3>
<p>{json.location.temp_c}</p>
<p>{json.location.localtime}</p>
</>
);
};
export default App;
When visiting either / or /weather, you will see the same results, since the example is implemented in both v12 and v13:
--- OR --- Implementing Fetch via Next.js 12
pages/weather.tsx
async function getData() {
const res = await fetch("/api/getWeather");
console.log("res", res);
// The return value is *not* serialized
// You can return Date, Map, Set, etc.
// Recommendation: handle errors
if (!res.ok) {
// This will activate the closest `error.js` Error Boundary
throw new Error("Failed to fetch data");
}
const json = await res.json();
console.log({ json });
return json;
}
export default async function Page() {
const data = await getData();
console.log("data", data);
return (
<main>
<h3>{data.location.name}</h3>
<p>{data.current.temp_c}</p>
<p>{data.location.localtime}</p>
</main>
);
}
pages/api/getWeather.ts
import { NextApiRequest, NextApiResponse } from "next";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const results = await fetch(
`http://api.weatherapi.com/v1/forecast.json?key=1d172d3904e246849d3183628230802&q=Stockholm&days=6&aqi=no&alerts=no`
);
const json = await results.json();
console.log("json", json);
res.status(200).send(json);
}
Remember to revoke your exposed secret API key.
I hope this helps you start building your app. Good luck!

I can't get header from backend in vuejs

I have a a spring boot backend that validates user login credentials. After validating the user it sends a login token in its response header. This part definitly works because I have seen it work in postman:
Now I am trying to get the token into my vuejs front end by doing the following:
import axios from 'axios'
const databaseUrl = 'http://localhost:9090/api'
const datbaseUrlBase = 'http://localhost:9090'
async function getSubjects(){
const result = await axios.get(`${databaseUrl}/subject`)
return result.data
}
async function updateSubject(subject){
let body = {
"name": subject.name,
"first_name": subject.first_name,
"date_of_birth": subject.date_of_birth
}
let result = await axios.put(`${databaseUrl}/subject/${subject.subjectid}`, body)
return result.data
}
async function getSubject(id){
let result = await axios.get(`${databaseUrl}/subject/${id}`)
return result.data
}
async function getSimulationsForSubject(id){
let result = await axios.get(`${databaseUrl}/subject/${id}/simulation`)
return result.data
}
async function deleteSubject(id){
await axios.delete(`${databaseUrl}/subject/${id}`)
}
async function makeSubject(subject){
await axios.post(`${databaseUrl}/subject`, subject)
}
async function updateDiagnose(diagnose, id){
await axios.put(`${databaseUrl}/subject/${id}/diagnose/${diagnose.diagnoseid}`, diagnose)
}
async function addSymptomToDiagnose(symptom, diagnoseid, subjectid){
await axios.post(`${databaseUrl}/subject/${subjectid}/diagnose/${diagnoseid}/symptom`, symptom)
}
async function updateSymptom(symptom_id, symptom, subjectid, diagnoseid){
await axios.put(`${databaseUrl}/subject/${subjectid}/diagnose/${diagnoseid}/symptom/${symptom_id}`, symptom)
}
async function getDiagnoseForSubject(diagnoseid, subjectid){
let result = await axios.get(`${databaseUrl}/subject/${subjectid}/diagnose/${diagnoseid}`)
return result.data
}
async function deleteSymptomForDiagnose(subjectid, diagnoseid, symptomid){
await axios.delete(`${databaseUrl}/subject/${subjectid}/diagnose/${diagnoseid}/symptom/${symptomid}`)
}
async function getStatisticsForSimulation(subjectid, simulationid){
let result = await axios.get(`${databaseUrl}/subject/${subjectid}/simulation/${simulationid}/statistics`)
return result.data
}
async function login(login){
let result = await axios.post(`${datbaseUrlBase}/login`, login)
return result.headers
}
export default{
getSubjects,
updateSubject,
getSubject,
getSimulationsForSubject,
deleteSubject,
makeSubject,
updateDiagnose,
addSymptomToDiagnose,
getDiagnoseForSubject,
deleteSymptomForDiagnose,
updateSymptom,
getStatisticsForSimulation,
login
}
Notice the login function above. Whenever I run this code the console.log gives undefined in the browser.
And the console.log(result.headers) gives this:
Is there anyway of accessing this token in my vuejs frontend?
If the server is cross-origin then browser CORS dictates that only a handful of default headers are accessible in a response.
You need to either have a matching origin, or enable the Access-Control-Expose-Headers header by setting it in your response like this:
Access-Control-Expose-Headers: token
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers

add API key to url

Hi I'm build a wildfire app tracker with react using the nasa API it works in development by using the url directly witch is https://eonet.sci.gsfc.nasa.gov/api/v2.1/events
But when I deploy it. It does not get the data. I obviously need a api key witch I have, but how do I implement it in the url above ?
here is my code..
useEffect(() => {
const fetchEvents = async () => {
setLoading(true)
const res = await fetch('https://eonet.sci.gsfc.nasa.gov/api/v2.1/events')
const {events} = await res.json()
setEventData(events)
setLoading(false)
}
fetchEvents()
// eslint-disable-next-line
}, [])
You could try to create a .env file in which you can set URLS as
REACT_APP_PUBLIC_URL=https://eonet.sci.gsfc.nasa.gov/api/v2.1/events
and then in your app component import as
fetch(process.env.REACT_APP_PUBLIC_URL)

getInitialProps in never called in NextJS

I have problem with getInitialProps method in NextJS. It is never called. This is project where I have Apollo GraphQL client for some pages and getInitialProps for other. I am not sure how to configure them correctly to work.
Apollo is working fine and fetching data as it should. Problem is that getInitialProps isn't called.
Here is my custom _app.js file
const App = ({ Component, pageProps, apollo }) => {
return (
<ApolloProvider client={apollo}>
<Component {...pageProps} />
</ApolloProvider>
)
}
const API_URL =
process.env.NODE_ENV === "development"
? "http://localhost/wordpress/index.php?graphql"
: "https://page/index.php?graphql"
export default withApollo(({ initialState }) => {
return new ApolloClient({
link: new createHttpLink({
uri: API_URL,
fetch: fetch
}),
cache: new InMemoryCache()
})
})(App, { getDataFromTree })
And here is how I call getInitialProps on page
Coupons.getInitialProps = async function() {
const res = await fetch('http://localhost:8000/data/');
const data = await res.json();
console.log(`Data fetched. Count: ${data.length}`);
return {
shows: data.map(entry => entry.show)
};
};
Also. Pages where I have Apollo fetching data doesn't need to call this REST API. Apollo pages and REST pages are totally different
This problem was fixed by following documentation on https://github.com/zeit/next.js/tree/canary/examples/with-apollo
Thing is that I wrapped whole _app in Apollo provider and right way is to wrap only pages that need Apollo in it.
Other that need getInitialProps should remain as is and call REST API in them.

redux test Actions must be plain objects. Use custom middleware for async actions

I am not using redux-thunk. this keeps error-ing and I am not sure how to fix it. The examples I see online use redux-thunk which I am not using
my repo is here and the file I am trying to test is in tests\actions\...
My action that is being called in the test
import axios from "axios";
var CancelToken = axios.CancelToken;
let fetch_cancel;
export const FETCH_CATEGORIES = "fetch_categories";
export async function fetchCategories() {
fetch_cancel && fetch_cancel();
const request = await axios.get(
`https://d1i9eedhsgvpdh.cloudfront.net/production-plentific-static/api-cache/find-a-pro/api/v1/categories/all.json`,
{
cancelToken: new CancelToken(function executor(c) {
// An executor function receives a cancel function as a parameter
fetch_cancel = c;
})
}
);
return {
type: FETCH_CATEGORIES,
payload: request
};
}
The error message means that your actions must be plain objects. For example:
store.dispatch({
type: 'ADD_TODO',
text: 'Understand the middleware'
})
If you make an async request, you can't just return an object, because you need to wait for the request to finish. If you return too early, you return a Promise.
However, I cannot reproduce your error in your sandbox.

Resources