I'm trying to get the current temperature from openweathermaps using axios.
I can put my url into the browser and it works fine. But when I try do an axios call with the correct url it doesnt event call.
Here is the relevant code section:
function Overview() {
const [temperature, setTemperature] = useState('')
const API_KEY = '{apikey}'
const getTemperature = useCallback(async () => {
const url = `https://api.openweathermap.org/data/2.5/weather?lat=${latitude.toFixed(2)}&lon=${longitude.toFixed(
2,
)}&appid=${API_KEY}`
console.log('my provided url is set to:', url)
const response = await axios.get(url)
if (response.data) {
setTemperature(response.data.main.temp)
}
}, [latitude, longitude])
useEffect(() => {
getTemperature().catch(console.error)
}, [getTemperature])
return <>{temperature ? temperature : 'no data'}</>
}
Any help as to where I'm going wrong would be great as I just cant see my error!
Your URL working on the browser showcases that your API key is correct. Now, make sure the variables in your URL are properly set from the code, particularly the API key. you can console.log them to be sure. Passed that, the minimal code below would do.
import {useCallback, useEffect} from 'react';
import axios from 'axios';
function Overview() {
// YOUR_INITIAL_STATE rather be undefined
const [temperature, setTemperature] = useState(YOUR_INITIAL_STATE);
const API_KEY = 'YOUR_API_KEY';
const getTemperature = useCallback(async () => {
const url = `https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=${API_KEY}`;
console.log("my provided url is set to:", url);
const response = await axios.get(url);
if(response.data){
setTemperature(response.data.main.temp);
}
// only call the functtion when these deps change
}, [latitude, longitude])
useEffect(() => {
// Check the error for further debbugging
getTemperature()
.catch(console.error);
}, [getTemperature])
return (
<>
{temperature ? temperature : "no data"}
</>
);
}
It looks like your arrow function is calling itself recursively:
const setTemperature = async () => {
const response = await axios.get(`https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=${API_KEY}`);
setTemperature(response.data.main.temp);
};
Your code doesn't show where this is being called. Probably it needs to be something like:
const setTemperature = async () => {
const response = await axios.get(`https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=${API_KEY}`);
return response.data.main.temp;
};
Perhaps it just needs to be a one letter change:
const getTemperature = async () => {
const response = await axios.get(`https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=${API_KEY}`);
setTemperature(response.data.main.temp);
};
Credit to #devklick
Related
This is a get request to get weather details of a location. Here's what my code looks like:
const [weather, setWeather] = useState(null);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
const [location, newLocation] = useState("Mumbai");
const locationHandler = (place) => {
newLocation(place);
};
const fetchweatherHandler = useCallback(async () => {
setIsLoading(true);
setError(null);
try {
console.log(location);
const response = await fetch(
`http://api.weatherapi.com/v1/current.json?key=<api_key>&q=${{
location,
}}&aqi=yes`
);
if (!response.ok) {
throw new Error("Something went wrong!");
}
const data = await response.json();
console.log(data);
setWeather(data);
} catch (error) {
setError(error.message);
}
setIsLoading(false);
weather && console.log(weather);
}, []);
useEffect(() => {
fetchweatherHandler();
}, [fetchweatherHandler]);
In the get request q="Mumbai" yields 200 status code but when replaced with ${{location}} so that weather can be displayed in terms of user input, yields a 400 status code.
I can't seem to understand why is this so.
Why are you doubling the curly braces in the template string? That creates an object, which isn't the output you want:
const test = "Mumbai";
console.log(`http://api.weatherapi.com/v1/current.json?key=<api_key>&q=${{test}}&aqi=yes`);
(You can, and should, observe this in your debugging by simply outputting the resulting value, or by observing the URL of the request in your browser's debugging tools.)
Just use one set of curly braces to evalutate the string value:
const test = "Mumbai";
console.log(`http://api.weatherapi.com/v1/current.json?key=<api_key>&q=${test}&aqi=yes`);
I am trying to send data from front-end to back-end. Here is my front:
import axios from 'axios'
const api = axios.create({
baseURL: `${process.env.BASE_FRONT_URL}`, // process.env.BASE_FRONT_URL = http://localhost:8010
})
export const postTip = async (payload) => {
try {
const { data } = await api.post(`post-tip`, payload);
return data;
} catch (e) {
return [];
}
};
And here is back-end:
const router = require('express').Router();
const tipController = require('../controllers/tips/tipController')
router.post('post-tip', tipController.postTip);
That function tipController.postTip actually just receive and shows data, but when I trigger this end-point I get error: POST http://localhost:8010/undefined/post-tip 404 (Not Found). So, what's wrong with end-point and how can I make it work? Also, I have no idea, where does this undefined come from? Am I missing something?
I have found my mistake. Actually process.env.BASE_FRONT_URL was really undefined, so, I made it like that:
import axios from 'axios'
const api = axios.create({
baseURL: 'http://localhost:8084',
})
export const postTip = async (payload) => {
try {
const { data } = await api.post(`post-tip`, payload);
return data;
} catch (e) {
return [];
}
};
But the most important thing is that on back-end I have to use the same port (8084)
when i use this code in goole console it works like this
but when i use same code in react-native there is only data in _url like this
I want to get values from searchParams.
this is my code
const Kakao = ({navigation}) => {
useEffect(() => {
Linking.addEventListener('url', async ({url}) => {
const urll = new URL(
'demo://app?accessToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6bnVsbCwicHJvdmlkZXIiOiJrYWthbyIsImlhdCI6MTYxODM5NDgwNX0.GfYs5rt0tjBrUmNvNIT6Bn_7TlJfY7zF9NxvkdqeTE0/',
);
console.log('urll.search', urll.search);
});
return () => Linking.removeEventListener('url');
}, []);
how can i fix my code to get a urll.search data ???
I am writing a test which tests a firebase trigger. The problem, however, is that I cannot make it work.
I want to use the local firestore emulator and Jest in order to simulate a change in the firestore and see if the trigger does what it needs to do.
I require the cloud function in my test and I initialize my app
Setup.js:
const firebase = require('#firebase/testing');
const PROJECT_ID = 'project';
let admin;
let db;
const setupAdmin = async () => {
admin = firebase.initializeAdminApp({
projectId: PROJECT_ID
});
db = admin.firestore();
};
const getAdmin = () => {
return admin;
};
const getDb = () => {
return db;
};
module.exports.setupAdmin = setupAdmin;
module.exports.getAdmin = getAdmin;
module.exports.getDb = getDb;
Test.js
describe('Billing', () => {
let dbRef;
beforeAll(async () => {
const {db, admin} = require('../../../functions/helpers/setup');
dbRef = db;
});
afterAll(async () => {
await Promise.all(firebase.apps().map(app => app.delete()));
console.log(`View rule coverage information at ${COVERAGE_URL}\n`);
});
it('test', async () => {
const mockData = {
'Users/user1': {
uid: 'user1'
},
['Users/user1/Taxes/' + new Date().getFullYear().toString()]: {
totalExpenseEuro: 0
}
};
for (const key in mockData) {
const ref = dbRef.doc(key);
await ref.set(mockData[key]);
}
// Create mockup data
await dbRef.collection('Users').doc('user1').collection('Expenses').doc('expense1').set({
amountEuroInclVAT: 100
});
// Make snapshot for state of database beforehand
const beforeSnap = test.firestore.makeDocumentSnapshot({amountEuroInclVAT: 0}, 'Users/user1/Expenses/expense1');
// Make snapshot for state of database after the change
const afterSnap = test.firestore.makeDocumentSnapshot(
{amountEuroInclVAT: 100},
'Users/user1/Expenses/expense1'
);
const change = test.makeChange(beforeSnap, afterSnap);
// Call wrapped function with the Change object
const wrapped = test.wrap(calculateTaxesOnExpenseUpdate);
wrapped(change, {
params: {
uid: 'test1'
}
});
});
});
Now the main problem comes when I try to access this db object in my trigger
const calculateTaxesOnExpenseUpdate = functions.firestore
.document('Users/{uid}/Expenses/{expenseId}')
.onWrite(async (change, context) => {
const {getDb} = require('../helpers/setup'); // This setup is the same as above
let db = getDb();
...
For some reason when I perform an action like (await db.collection('Users').get()).get('totalExpenseEuro'), Jest stops executing my code. When I set a debugger right after that line, it never gets printed. That piece of code crashes, and I have no idea why. I think the DB instance if not properly configured in my cloud trigger function.
Question: What is a good way of sharing the DB instance (admin.firestore()) between the test and the cloud trigger functions?
I have two components which i am working with. In the first component, i made a custom useEffect hook that retrieves data from my server. Please see the code below:
Code snippet One
import {useState, useCallback} from 'react';
import {stageQuizApi} from '../api/quiz';
import {QuestionService} from "../services/IdDbServices/question_service";
const usePostData = ({url, payload, config}) => {
const [res, setRes] = useState({data: null, error: null, isLoading: false});
const callAPI = useCallback(() => {
setRes(prevState => ({...prevState, isLoading: true}));
stageQuizApi.patch(url, payload, config).then( res => {
setRes({data: res.data, isLoading: false, error: null});
const questionInDb = {};
const {NoTimePerQuestion,anwser, question, playerDetails, option} = res.data.data;
const {playerid,anwserRatio, name} = playerDetails
questionInDb.timePerQuestion = NoTimePerQuestion;
questionInDb.anwserRatio = anwserRatio;
questionInDb.options = option;
questionInDb.answer = anwser;
questionInDb.playerId = playerid;
questionInDb.name = name;
questionInDb.question = question;
const Service = new QuestionService();
Service.addStudent(questionInDb).
then(response=>console.log(response))
.catch(err=>console.log(err));
}).catch((error) => {
console.log(error)
if (error.response) {
const errorJson = error.response.data
setRes({data: null, isLoading: false, error: errorJson.message});
} else if (error.request) {
setRes({data: null, isLoading: false, eror: error.request});
} else {
setRes({data: null, isLoading: false, error: error.message});
}
})
}, [url, config, payload])
return [res, callAPI];
}
export default usePostData;
The above module has two purpose. It first makes an axios request to my endpoint and secondly makes a database insertion to browser IndexDb (similar to localstorage but with sql approach) ( like inserting data into the database using the response that was gotten from the first request. so typically i have a promise in the outer .then block. This part:
Code snippet Two
const questionInDb = {};
const {NoTimePerQuestion,anwser, question, playerDetails, option} = res.data.data;
const {playerid,anwserRatio, name} = playerDetails
questionInDb.timePerQuestion = NoTimePerQuestion;
questionInDb.anwserRatio = anwserRatio;
questionInDb.options = option;
questionInDb.answer = anwser;
questionInDb.playerId = playerid;
questionInDb.name = name;
questionInDb.question = question;
const Service = new QuestionService();
Service.addStudent(questionInDb).
then(response=>console.log(response))
.catch(err=>console.log(err));
Here is the problem, I am trying to maintain state as i want the result of this module to be shared in another route and i don't want to hit the server again hence i inserted the result into indexDb browser storage. Here is the code that executes the above module:
Code snippet Three
const displaySingleQuestion = ()=>{
OnUserGetQuestion();
history.push('/player/question');
}
The above method is called from my first route /question and it is expected to redirect user to the /player/question when the displaySingleQuestion is called.
On the new route /player/question i then want to fetch the data from IndexDb and update the state of that component using the useEffect code below:
Code snippet Four
useEffect(()=>{
const getAllUserFromIndexDb = async()=>{
try{
const result = await new Promise((resolve, reject) => {
service.getStudents().then(res=>resolve(res)).catch(err=>reject(err))
});
console.log('it did not get to the point i was expecting',result)
if(result[0]){
console.log('it got to the point i was expecting')
const singleQuestion = result[0];
const questionPage = playerQuestionToDisplay;
questionPage.name = singleQuestion.name;
questionPage.anwserRatio = singleQuestion.anwserRatio;
questionPage.answer = singleQuestion.answer;
questionPage.options = singleQuestion.options;
questionPage.playerId = singleQuestion.playerId;
questionPage.question = singleQuestion.question;
questionPage.timePerQuestion = singleQuestion.timePerQuestion;
return setplayerQuestionToDisplay({playerQuestionToDisplay:questionPage})
}
}
catch(error){
console.log(error)
}
}
getAllUserFromIndexDb();
return function cleanup() {
setplayerQuestionToDisplay({playerQuestionToDisplay:{}})
}
},[history.location.pathname]);
The problem is that only one Button click (Code snippet three)(displaySingleQuestion()) triggers the whole functionality and redirect to the /player/question page but in this new route the state is not been set until a page reload as occurred, i tried debugging the problem and i found out that when the button is clicked i found out that Code snippet two is executed last hence when Code snippet Four ran it was in promise and until a page reloads occurs the state of the component is undefined
Thanks for reading, Please i would appreciate any help in resolving this issue.