I'm trying to fetch the json data using axios. Could you please tell me what am i doing wrong here
I have tried doing it using hooks as well but to no avail. i have put it below the class based component please have a look at it. Could you please tell me what am i doing wrong here
API : https://newsapi.org/v2/top-headlines?sources=bbc-news&apiKey=API_KEY
API_ KEY : 3055f8f90fa44bbe8bda05385a20690a
import React, { Component } from "react";
import axios from "axios";
import Post from "../../Component/Post/Post";
export default class Home extends Component {
state = {
posts: [],
};
componentDidMount() {
axios
.get(
"https://newsapi.org/v2/top-headlines?sources=bbc-news&apiKey=API_KEY",
{
headers: {
" API_KEY ": "3055f8f90fa44bbe8bda05385a20690a",
},
}
)
.then((response) => {
console.log(response.data);
this.setState({ posts: response.data });
})
.catch((err) => {
console.log("API call error:", err.message);
});
}
render() {
const posts = this.state.posts.map((post) => {
return <Post key={post.id} />;
});
return <div>{posts}</div>;
}
}
import React, { useState, useEffect } from "react";
import Post from "../../Components/Post/Post";
import axios from "axios";
const HomePage = () => {
const [posts, setPosts] = useState("");
let config = { Authorization: "3055f8f90fa44bbe8bda05385a20690a" }; //3055f8f90fa44bbe8bda05385a20690a
const url =
"https://newsapi.org/v2/top-headlines?sources=bbc-news&apiKey=API_KEY";
useEffect(() => {
AllPosts();
}, []);
const AllPosts = () => {
axios
.get(`${url}`, { headers: config })
.then((response) => {
const allPosts = response.data;
setPosts(allPosts);
})
.catch((error) => console.error(`Error: ${error}`));
};
return (
<div>
<Post className="Posts" posts={posts} />
</div>
);
};
export default HomePage;
Replace your previous codes with this:
let config = {'Authorization': 'MY-API-KEY'};//3055f8f90fa44bbe8bda05385a20690a
axios.get('https://newsapi.org/v2/top-headlines?sources=bbc-news&apiKey=API_KEY', {headers: config})
Also, refer to this question to get a deep understanding of the problem:
Setting authorization header in axios
Related
I am using tokens around my ReactJS application. This is how I can get the value of the token in a page:
pages/Profile.js
import React from 'react';
import useToken from '../useToken';
export default function Profile() {
// Get token
const { token, setToken } = useToken();
const { userObject } = useToken();
return(
<div>
<p>
<b>Name:</b> {userObject?.name}<br />
<b>Email:</b> {userObject?.email}<br />
<b>Token:</b> {token}
</p>
</div>
);
}
Now I want to use the token inside a component. However the same appoch did not work, as it gives me an error "Unexpected token. A constructor, method, accessor, or property was expected.ts(1068)".
components/MyKnownDevices.js
import React from 'react';
import axios from 'axios';
import useToken from '../useToken';
export default class MyKnownDevices extends React.Component {
// Get token
const { token, setToken } = useToken(); // <---- THIS GIVES ERROR
const { userObject } = useToken(); // <---- THIS GIVES ERROR
// Respone handler
state = {
myKnownDevices: []
}
// Call API
componentDidMount() {
let config = {
headers: {
Accept: 'application/json',
'Access-Control-Allow-Origin': '*',
rejectUnauthorized: false,
}
}
let data = {
'HTTP_CONTENT_LANGUAGE': 'no',
rejectUnauthorized: false,
}
axios.get('https://127.0.0.1:5000/api/users/get_my_known_devices', data, config)
.then(res => {
const myKnownDevices = res.data;
this.setState({ myKnownDevices });
})
};
render() {
return (
<ul>
{
this.state.myKnownDevices
.map((device, index) => {
return (
<li key={index}>
<span>{device.known_device_updated_timestamp_saying}</span>
</li>
);
}
)
}
</ul>
)
};
};
useToken.js
import { useState, useEffect } from 'react';
import jwt_decode from "jwt-decode"
// const userObject = null;
export default function useToken() {
// Get token
const getToken = () => {
const userToken = localStorage.getItem('token');
return userToken
};
// Consts
const [token, setToken] = useState(getToken());
const [userObject, setUserObject] = useState(null);
// Effect
useEffect(() => {
if(token && token !== "undefined" && !userObject){
setUserObject(jwt_decode(token));
}
},[token]);
// Save token
const saveToken = userToken => {
if(userToken === null){
localStorage.removeItem('token');
setToken(null);
}
else{
localStorage.setItem('token', userToken.token);
setToken(userToken.token);
}
};
// Return value
return {
setToken: saveToken,
token,
userObject,
}
}
How can I get the value of the token inside my component MyKnownDevices.js?
This issue here is that useToken is a hook (https://reactjs.org/docs/hooks-intro.html) and hooks can only be used in functional components.
Given your code, I think the simplest way would be to rewrite your class component as a functional component, this should do the trick :
import React, {useEffect, useState} from "react";
import axios from "axios";
import useToken from "../useToken";
export default function MyKnownDevices() {
// Get token
const { token, setToken, userObject } = useToken();
const [myKnownDevices, setMyKnownDevices] = useState([]);
// Call API
// This is the same thing as your componentDitMount
useEffect(() => {
let config = {
headers: {
Accept: "application/json",
"Access-Control-Allow-Origin": "*",
rejectUnauthorized: false,
},
};
let data = {
HTTP_CONTENT_LANGUAGE: "no",
rejectUnauthorized: false,
};
axios
.get(
"https://127.0.0.1:5000/api/users/get_my_known_devices",
data,
config
)
.then((res) => {
const myKnownDevices = res.data;
setMyKnownDevices(myKnownDevices);
});
}, []);
return (
<ul>
{myKnownDevices.map((device, index) => {
return (
<li key={index}>
<span>{device.known_device_updated_timestamp_saying}</span>
</li>
);
})}
</ul>
);
}
You must not use react hooks inside class components. You should rewrite your class component to functional
I am trying to fetch some data from a Football API. For example, the countries that are provided by the API. I could get the data in the console.log but as soon as I try to render it, I get this error : Uncaught TypeError: (0 , axios__WEBPACK_IMPORTED_MODULE_0__.useState) is not a function or its return value is not iterable.
Here is the code :
import axios from 'axios';
import './App.css';
import { useState } from 'axios';
import React from 'react';
function Ui() {
const [country, setCountry] = useState('')
const options = {
method: 'GET',
url: 'https://api-football-v1.p.rapidapi.com/v3/countries',
headers: {
'X-RapidAPI-Key': '',
'X-RapidAPI-Host': 'api-football-v1.p.rapidapi.com'
}
};
const getCountry = () => {
axios.request(options).then(function (res) {
setCountry(res.data.response);
}).catch(function (error) {
console.error(error);
})
}
return (
<>
<button onClick={getCountry}>Get Country</button>
<p>{country}</p>
</>
);
}
export default Ui;
You're trying to import useState from Axios instead of React.Change it to this: import React, {useState} from 'react'; and for Axios: import axios from 'axios'; You're also importing axios twice.
You shouldn't add the api-key here either. You might want to look at your code again.
Example to print all the country names (put in the API key where it says API-KEY):
import axios from "axios";
import React, { useState, useEffect } from "react";
function Ui() {
const [country, setCountry] = useState([]);
useEffect(() => {
axios
.get("https://api-football-v1.p.rapidapi.com/v3/countries", {
headers: {
"X-RapidAPI-Key": "API-KEY"
}
})
.then((res) => {
setCountry(res.data.response);
})
.catch((err) => console.log(err));
}, []);
return (
<>
<button>Get Country</button>
<div>
{country.map((data, i) => (
<h1>{data.name}</h1>
))}
</div>
</>
);
}
export default Ui;
I have created an Axios instance and a notificationContext to use in a React webapp.
I want to access the addNotification function of the notificationContext inside the request/response interceptor of the created Axios instance but since this is not a React component it's not possible. Is there a way to make and use this created Axios instance and interceptors as a React component?
NotificationContext.js
import React, { createContext, useState } from 'react';
const NotificationContext = createContext();
const NotificationProvider = ({ children }) => {
const [notifications, setNotifications] = useState([]);
const addNotification = (type, title, description) => {
const notification = {
id: Date.now(),
type,
title,
description,
};
setNotifications([notification, ...notifications]);
};
const removeNotification = (id) => {
setNotifications(notifications.filter((notification) => notification.id !== id));
};
return <NotificationContext.Provider value={{ notifications, addNotification, removeNotification }}>{children}</NotificationContext.Provider>;
};
export { NotificationContext, NotificationProvider };
App.js
The NotificationProvider is wrapped around the NotificationList component
const App = () => (
<BrowserRouter>
<AuthProvider>
<NotificationProvider>
<NotificationList />
<Router />
</NotificationProvider>
</AuthProvider>
</BrowserRouter>
);
export default App;
apiClient.js
import axios from 'axios';
// import { useContext } from 'react';
// import { NotificationContext } from '../context/NotificationContext';
const apiClient = axios.create({
baseURL: process.env.REACT_APP_API,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
withCredentials: true,
timeout: 10000,
});
apiClient.interceptors.request.use(
(config) => {
return config;
},
(error) => {
return Promise.reject(error);
// How to access AddNotification here
},
);
apiClient.interceptors.response.use(
(response) => {
return Promise.resolve(response);
},
(error) => {
if (!error.response) {
// network error
// console.log('Network error');
// How to access AddNotification here
} else {
const response = error.response.data;
// How to access AddNotification here
}
return Promise.reject(error);
},
);
export default apiClient;
You can export the axios instance
create a functional component
access the context
init interceptor in useMemo
Example (just for an idea):
function Interceptor({children}) {
const {addNotification} = useContext(NotificationContext)
useMemo(() => {
apiClient.interceptors.response.use(
(response) => {
return Promise.resolve(response);
},
(error) => {
if (!error.response) {
addNotification()
} else {
const response = error.response.data;
addNotification()
}
return Promise.reject(error);
},
);
}, [addNotification])
return <>{children}</>
}
and in App.js
const App = () => (
<BrowserRouter>
<AuthProvider>
<NotificationProvider>
<Interceptor> // here
<NotificationList />
<Router />
<Interceptor />
</NotificationProvider>
</AuthProvider>
</BrowserRouter>);
export default App;
I want to integrate to React query for fetching the data from server.
So far I've been fetching the rest api via Axios.
I have created a custom hook for fetching and want to transform and implement with react query.
While trying to implement the same logic I encountered an error trying to destructure the fetched data const { data } = useApiRequest(headersUrl):
error - TypeError: (0 , _hooks_useApiRequest__WEBPACK_IMPORTED_MODULE_1__.UseApiRequest) is not a function
Here is the old logic for fetching
import * as React from "react";
import { useState, useEffect } from "react";
import axios from "axios";
import { HeaderToken } from "../services/api";
export const useApiRequest = (url: any) => {
const [data, setData] = useState<[] | any>([]);
useEffect(() => {
const fetchData = () => {
axios
.get(url, {
headers: {
Authorization: `Basic ${HeaderToken}`,
},
})
.then((response) => {
setData(response.data);
})
.catch((error) => console.error(error));
};
fetchData();
}, [url]);
return { data };
};
And here is how I'm trying to convert it:
import { HeaderToken } from "../services/api";
import { useQuery } from "react-query";
export const useApiRequest = (url: any) => {
const { isLoading, data } = useQuery("bc", async () => {
const response = await fetch(url, {
method: "get",
headers: {
Authorization: `Basic ${HeaderToken}`,
"Content-Type": "application/json",
},
});
if (!response.ok) throw new Error(response.statusText);
return await response.json();
});
return { data };
};
I can't see the problem, actually, I tried the same code you shared with a local API I have and it's working
The Hook
import { useQuery } from 'react-query'
export const clientAPI = (url) => {
const { isLoading, data } = useQuery("bc", async () => {
const response = await fetch(url, {
method: "get"
});
if (!response.ok) throw new Error(response.statusText);
return await response.json();
});
return { data };
};
React Component
import * as React from "react";
import { clientAPI } from "../hooks/clientAPI";
export default function Home() {
const { data } = clientAPI('http://localhost:5000/')
return (
<div>
{JSON.stringify(data)}
</div>
)
}
_app.js
import { QueryClient, QueryClientProvider, useQuery } from 'react-query'
const queryClient = new QueryClient()
function MyApp({ Component, pageProps }) {
return (<QueryClientProvider client={queryClient}>
<Component {...pageProps} />
</QueryClientProvider>)
}
export default MyApp
I'm using next#11.1.2, react-query#3.28.0
what are the versions you are using?
I have two custom hooks i.e useFetch and useAuth. useAuth has all API calls methods (e.g logIn, logOut, register, getProfile etc) and they use useFetch hook method for doing API calls. useFetch also uses these methods for example logOut method when API return 401, setToken etc. So, they both need to share common methods. But that results into circular dependency and call size stack exceeded error. How to manage this
UseFetch.js
import React, { useState, useContext } from "react";
import { AuthContext } from "../context/authContext";
import { baseURL } from "../utils/constants";
import { useAuth } from "./useAuth";
const RCTNetworking = require("react-native/Libraries/Network/RCTNetworking");
export const useFetch = () => {
const {token, setAuthToken, isLoading, setIsLoading, logIn, logOut} = useAuth();
const fetchAPI = (method, url, body, isPublic, noBaseURL) => {
setIsLoading(true);
const options = {
method: method
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
},
};
return fetch(url, options, isRetrying).then(() => {
......
})
......
};
return { fetchAPI };
};
UseAuth.js
import React, { useContext, useEffect } from "react";
import { AuthContext } from "../context/authContext";
import { useFetch } from "./useFetch";
export const useAuth = () => {
const {
removeAuthToken,
removeUser,
setUser,
...others
} = useContext(AuthContext);
const { fetchAPI } = useFetch();
const register = (body) => {
return fetchAPI("POST", "/customers/register", body, true);
};
const logIn = (body) => {
return fetchAPI("POST", "/customers/login", body, true);
};
const logOut = () => {
return (
fetchAPI("POST", "/customers/logout")
.catch((err) => console.log("err", err.message))
.finally(() => {
removeAuthToken();
removeUser();
})
);
......
};
return {
...others,
register,
logIn,
logOut,
};
};