I am having trouble using an API as it keeps making an https call and not an http call. The https call is behind a paywall and the free version of the api only supports http calls. I am using https://weatherstack.com/ API.
I am using react with the axios package to make my HTTP calls.
import React, { useState, useEffect } from 'react'
import axios from 'axios'
const Weather = (props) => {
const [response, setResponse] = useState([])
const hook = () => {
axios
.get(`http://api.weatherstack.com/current?access_key=${process.env.REACT_APP_API_KEY}&query=${props.country.capital}`)
.then(response => {
console.log('promise fulfilled')
setResponse(response.data)
})
}
useEffect(hook, [])
console.log(response)
return (
<div>Temperature: {} </div>)
}
export default Weather
The error message I receive from the API is this
info: "Access Restricted - Your current Subscription Plan does not support HTTPS Encryption."
type: "https_access_restricted"
The strange thing is about 20% of the time the call works and I can get my data, but it doesn't work most of the time. TIA
Related
I have a react project where I'm making requests to a third-party api. I created an axios file where I set a baseUrl for requests, and I export a function which will make a request to a particular endpoint.
However, when I import and execute the function in my App.js, the request is made with localhost:3000 as the base url. Can't figure out why
I made a sandbox to demonstrate
here is the code for my axios.js file
import axios from 'axios'
const instance = axios.create({
baseUrl: `https://api.-----.com/svc/topstories/v2/`
})
export const api_key = '------------------------'
export const getTopStories = async () => {
const {data: {results}} = await instance.get(`/home.json?api-key=${api_key}`)
return results
}
export default instance
You should use baseURL instead of baseUrl
I've installed axios by this command:
npm i axios
I wrote the code below and everything I think is correct but React-Native doesn't show any data and throw any errors:
import React, {useState, useEffect} from 'react';
import axios from 'axios';
import {
View,
Text,
StyleSheet
} from 'react-native';
const App = () => {
const [data, setData] = useState([]);
useEffect(() => {
axios.get('http://localhost:8000/posts').then(res => {
setData(res.data);
});
}, []);
return (
<View style={styles.mainBody}>
{
data.map(item => (
<View>
<Text>{item.fields.title}</Text>
</View>
))
}
</View>
);
};
I've tested functional and class-based components for this.
I fetch data with Postman and works correctly.
I added .catch and it shows this: Error: Network Error
But it doesn't work on React-Native and because of no errors, I can't understand what's my problem. Any help will be appreciated.
It's because you're using localhost in your URL, with react-native we cant use localhost but instead, we use the IPv4 address of our computer. So click on your wifi icon then click on the properties then look for IPv4 address something like: 193.93.443
So if to say your IPv4 address is 193.93.443, the local URL will be like this: http://193.93.443:8000/posts
I need to mock useLogin hook, bacause it contains logic that throws an error. Later i will test it in isolationю. UseLogin returns loading flag and login function that connecting new user to firebase.
import useLogin from "../../../hooks/useLogin";
export default function Login({ register, handleSubmit }) {
const [loading, login] = useLogin();
return (
<Form onSubmit={handleSubmit(login)}>
{...other components}
<Form>
);
}
useLogin hook
import { useState } from "react";
import { useHistory } from "react-router";
import { useModalContext } from "../../context";
import { firebase } from "../../libs/firebase";
export default function useLogin() {
const [loading, setLoading] = useState(false);
const [, { showErrorModal }] = useModalContext();
const history = useHistory();
function login({ email, password }) {
setLoading(true);
firebase
.auth()
.signInWithEmailAndPassword(email, password)
.then(() => {
setLoading(false);
history.push("/");
})
.catch(() => {
setLoading(false);
showErrorModal("User not found");
});
}
return [loading, login];
}
You should avoid mocking your own components when possible, as you will need to maintain both component and mock if you change the component code. You can still test this and test the useLogin hook isolated, to test all different code branches and so on.
The recommendation when going to the outside world and make API requests, is to use a library that allows you to mock them without being intrusive. Libraries like nock or Mock Service Worker let you do exactly that, and this way you avoid mocking fetch.
That said, in case you need to mock this, you can mock the firebase library to return whatever is needed. You can do it with a regular Jest mock, or try this firebase-mock library in case you will need to mock more of firebase features and here you can see how it integrates with Jest.
Creating your own custom mock might be the quicker option, and if you don't need to mock anything else, it might be the best option as well. Here you can see an example of a custom firebase mock: Mock implementation of firebase auth methods after mocking the firebase module
Been quite stuck for the past week or so and cannot find any answers to my issue. Today I started doing some proper investigating. It looks like Axios is not working when firing events. This also does not work on my main PC either which makes me think it's actually a bug with Axios.
I have already tried:
Reinstalling Axios independently
Uninstalling all global dependencies I have
Creating a new React App
Checking the events are firing (which they are)
Checking my network tab (nothing shows up)
My post request is working fine when just calling it as a function:
import React from "react";
import axios from "axios";
import "./App.css";
function App() {
const makeRequest = () => {
axios.post("http://localhost:5000");
};
makeRequest();
return <div className="app"></div>;
}
export default App;
Backend output: There was a post request!
However, my code does not work when using events, this goes for onClick and onSubmit (that's what I have tested anyway):
import React from "react";
import axios from "axios";
import "./App.css";
function App() {
const makeRequest = () => {
axios.post("http://localhost:5000");
};
return (
<div className="app">
<button onClick={makeRequest}>Post Request</button>
</div>
);
}
export default App;
No backend output or frontend output. Help would be much appreciated!
Edit: Something I forgot to mention was that fetch works absolutely fine, but I'd really rather use Axios where possible.
Change your const to a function and call it with an object passthrough method.
import React from "react";
import axios from "axios";
import "./App.css";
function App() {
function makeRequest (){
axios.post("http://localhost:5000");
};
return (
<div className="app">
<button onClick={() => makeRequest()}>Post Request</button>
</div>
);
}
export default App;
Try to add more console.log calls to grab more debug data from frontend - it can help to solve the problem.
import React from "react";
import axios from "axios";
import "./styles.css";
export default function App() {
const makeRequest = () => {
const result = axios
.post("https://jsonplaceholder.typicode.com/users")
.then((result) => {
console.log("Result", result);
})
.catch((error) => console.error("Error", error))
.finally(() => console.log("Request has been made"));
console.log("Result should be a Promise object", result);
};
return (
<div className="app">
<button onClick={makeRequest}>Post Request</button>
</div>
);
}
The code snippet above works totally fine. Check the code snippet here, and try to run it on your environment. If the information in console logs will not appear or either didn't help – dig into your environment and tools which you use to transpile JSX code, build JS and add that information to the question. Probably the problem is hidden somewhere in there.
Kindly check if you have "proxy": "localhost:5000" in your react app package.json file, this will allow React to proxy API requests to the Node.js server built with Express.
5000 is the node server port.
The problem is that your're passing the funcion instead of calling it.
I would try using an arrow funcion in onClick likt this :
onclick={()=> makeRequest()}
I can see you are not invoking the function with (), it should be makeRequest()
I want to handle axios errors unifiedly when the response's status code is not 2XX or 3XX.
For example, requests for captchas, the backend will return 429 status code if there are too many requests in a short time sent from one client.
models/Captcha.js
import axios from 'axios';
class Captcha{
static async store(){
const { data } = await axios.post(`${process.env.API_URL}/auth/captchas`);
return data;
}
}
export default Captcha;
plugins/axios-interceptor.js
import axios from 'axios';
// after getting response
axios.interceptors.response.use(
response => {
return response;
},
error => {
// handle errors unifiedly here
handleErrors(error);
}
);
in nuxt.config.js
plugins:[
'~/plugins/axios-interceptor'
],
pages/register.vue
<template>
...
<img :src="captcha.image_content" #click="refreshCaptcha()">
...
</template>
import Captcha from '#/models/Captcha';
export default{
async asyncData(){
const captcha = await Captcha.store();
return {
captcha: captcha
}
},
methods:{
async refreshCaptcha(){
this.captcha = await Captcha.store();
}
},
...
}
But it can't work as I expected.
First, I don't want to have the default errors handler by Nuxt.js
Second, it can't handle errors happened in node.js, I want to render the page normally when errors occurred
How can I solve it? I don't want to use callback instead of Promise or async function, because the Nuxt.js Official said they will not support it any longer in the future.
Thanks a lot!
The asyncData command runs on the server side and you can not use the methods and services you wrote on the client side in asyncData. In fact, the contents of asyncData are called before your project loads.