I tried to create an application from an Random user API in react and I used axios library for HTTP Requests.I created a separate file for base API using axios.create and the file code goes as,
import axios from 'axios'
export default axios.create({
baseURL: `http://jsonplaceholder.typicode.com`,
});
Then I used this in another file to make an GET request and store the data in state on componentdidMount so ill can access the data in UI.
import React from "react";
import API from "../api";
export default class PersonList extends React.Component {
state = {
persons: []
};
componentDidMount() {
API
.get('/').then((data) => {
const persons = data.data;
this.setState({ persons });
console.log(this.state.persons);
});
}
render() {
const { persons } = this.state;
console.log('Stato',persons)
return (
<ul>
{persons.map((person) => (
<li key={person.id}>{person.name}</li>
))}
</ul>
);
}
}
But it doesn't work ,because the state is not filled up with Users data,so the .map() function is throwing an error.
You're encountering this error because of the URL you are using. In your example, you use https://jsonplaceholder.typicode.com as the endpoint in componentDidMount, but that isn't going to return any placeholder user data. I believe you meant to use https://jsonplaceholder.typicode.com/users instead.
I have a working example here: https://codesandbox.io/s/axios-instance-ki9g6. Notice how I only had to change / in componentDidMount to /users.
Related
I'm trying to write an API service in a React app, using Axios and Typescript.
Below is my code:
Interface for Helper API Class
import { AxiosResponse } from 'axios'
export interface PlatformResponse {
platform: {
id: string
image: string
name: string
}[]
}
export interface Platform {
getPlatformResponse: () => Promise<AxiosResponse<PlatformResponse>>
}
My Platform Class
import { AxiosResponse } from 'axios'
class Platforms implements Platform {
async getPlatformResponse(): Promise<AxiosResponse<PlatformResponse>> {
const path = 'http://localhost:8080/api/platforms'
const method = 'get'
const result = await httpRequest({ path, method })
return result
}
}
const PlatformsAPI = new Platforms()
export default PlatformsAPI
I'm using the react-query library for fetching data, and the code below
const useGetPlatforms = () => {
console.log('sdfd')
return useQuery('platform', PlatformsAPI.getPlatformResponse)
}
export default useGetPlatforms
And the Code for my component as below
import { useGetVehicleBrands } from '../../../hooks/RQHooks'
function VehicleBrands() {
const { data, isLoading } = useGetVehicleBrands()
console.log('data', data.platform)
return (
<>
<div>
{data.platform.map((item) =><h1>{item}</h1>)}
</div>
</>
)
}
export default PlatformComponent
The error I'm getting in my above code is that I couldn't access the platform property from the data. Typescript throwing error saying that the platform property not found. Only the property from the AxiosResponse is shown. How to accomplish that the typescript know that data is the type of PlatformResponse. Kindly help to accomplish it.
you get a data property from react-query that contains the unwrapped promise from whatever your queryFn returns.
an AxiosResponse contains what you're seeing in your screenshot - data, headers, statusText etc.
Your actual data is inside the data property, so you'd need:
data.data.platform
The first data being the one from react-query, the second one being the one from axios.
If you don't need to store request meta-data like headers in your queryCache, it is best to unwrap it inside the queryFn:
useQuery(
'platform',
() => PlatformsAPI.getPlatformResponse().then(response => response.data))
)
you can also do that inside your PlatformsAPI if you want.
I have multiple routes in my app and I have added Auth0 in Header.js (a child of App.js) to be able to keep the user logged-in amongst all the routes. I was also able to get Auth0 user prop object (name, email, and picture) to create accounts for the users in my database.
Now in another child component of App.js (Feed.js), I'm trying to use the email from Auth0 props as a query parameter to send a GET request to the database, but each time I do so I either receive an error (user is not found) or undefined.
Feed.js code looks like this:
import React, { Component } from 'react'
import axios from "axios";
import { withAuth0 ,auth0} from '#auth0/auth0-react';
class Feed extends Component {
constructor(props){
super(props);
this.state={
userdata:[]
}
}
getdata = async() => {
await axios
.get(`http://localhost:1177/getuser?email=this.props.auth0.user.email`)
.then((res) => {
this.setState({
userdata: res.data,
});
});
};
render() {
this.getdata();
return (
<div>
<img src={this.state.userdata.pp} alt={this.state.userdata.username} />
<h1>{this.state.userdata.username}</h1>
<h1>{this.state.userdata.email}</h1>
</div>
)
}
}
export default withAuth0(Feed)
So any ideas on how to make this work?
You might have an error because the expression used in the template literal is not correctly typed between a dollar sign and curly braces in the GET request.
Try this:
`http://localhost:1177/getuser?email=${this.props.auth0.user.email}`;
I am building a site just like stackoverflow.com. I want my home page to display top questions. For that, I have sample questions on the backed. Now, I want to display only the question and tags from the questions array.
The code is in the image
I have made axios connection for that:
const instance = axios.create({
baseURL: "https://2w2knta9ag.execute-api.ap-south-1.amazonaws.com/dev", });
instance.defaults.headers.post["Content-Type"] = "application/json";
To connect it, I wrote the command: instance.get("/questions)
Now, how do I display only the question and tags??
EDIT:
On using the code given bellow, my js file now becomes:
import React from 'react';
import instance from '../../api';
class QuestionList extends React {
componentDidMount() {
instance
.get("/questions")
.then((res) => {
this.setState({ data: res.data });
});
}
render () {
const { data } = this.state;
return <div>
{
data && data.map(d => {
return <div>question: {d.question}, tags: {d.tags}</div>;
})
}
</div>
}
}
export default QuestionList;
But, this is just making my site in a loading state, and it gets hanged!!
If I understood correctly, you want to get an array only with the tags and the question. if so, you can use Array.prototype.map for this
const questions = result.map(({ question, tags }) => ({ question, tags }))
First you export the axios instance so that it can be used from other components.
Now you can send the api request in componentDidMount and update your component's state with the data.
And in render function, you just get the value from state and display.
If you are new to react, learn React Hooks and know that componentDidMount method is the best place to send api requests.
For Example:
import React from 'react';
import instance from '../../api';
class QuestionList extends React.Component {
constructor() {
super();
this.state = {
data: [],
};
}
componentDidMount() {
instance.get('/questions').then((res) => {
this.setState({ data: res.data });
});
}
render() {
const { data } = this.state;
return (
<div>
{data &&
data.map((d) => {
return (
<div>
question: {d.question}, tags: {d.tags}
</div>
);
})}
</div>
);
}
}
export default QuestionList;
I have a need to fetch data from an API on component load, am using axios to fetch data, I need to save the response to the state and get back when the component load.
But i could do as am new to this.
My codes as below.
Sales.js : (This is where I fetch My components)
function SalesDesk() {
return (
<div>
<FoodScreen />
</div>
)}
export default SalesDesk;
FoodScreen.js (This is where i need to list my results to a variable, to map it later)
function FoodScreen() {
return(
<div className="sdFoodScreenMain">
{console.log(items)} // The results should be displayed here
</div>
)}
export default FoodScreen;
API.js (Here is where where i use my axios Router)
const API_URL = `https://jsonplaceholder.typicode.com/`; //Mock api for test purposes
export const GetAllItems = () => {
return (dispatch) => {
axios.get(API_URL)
.then(response => {
dispatch(allItemsList(response.data));
})
}
};
ItemsReducer.js (The reducer Logic)
const ItemsReducer =(state:Array = null, action) =>{
if (action.type === 'ALL_ITEMS') {
return GetAllItems ;
} else {
return state= null;
}
};
export default ItemsReducer
SalesAction.js (Action list)
export const allItemsList = () => {
return {
type: 'ALL_ITEMS'
};
};
All I need to do is fetch the the data from the API and display it in the console, when the component renders.so that I can display it in a map of div boxes for future purposes. Am new to both react and Redux, so ignore if any logic or implementation issues.
At first Router.js is a bad name(api.js etc), You should connect Sales.js to redux, using { connect } from 'react-redux'. See there https://redux.js.org/basics/usage-with-react and call action to fetch data in Sales.js
All I had to add an useDispatch on the component render, so it could fetch the data to the component on load.
import Reactfrom 'react'
import {useDispatch} from "react-redux";
import {GetAllItems} from 'API' //File containing the axios function
export function SalesDesk() {
const dispatch = useDispatch();
dispatch(GetAllItems())
return (
<div>
<FoodScreen />
</div>
)}
This helped me to fetch add add to state on component load.
When I call my API via my web browser I get the following result:
{"statusCode": 200, "body": "\"Cheers from AWS Lambda!\""}
However, I am now struggeling to show body via axios. Do you see what I am doing wrong?
import axios from "axios";
import React, { Component } from "react";
class App extends Component {
state = {
messages: []
};
componentDidMount() {
axios
.get(
"https://12345.execute-api.eu-central-1.amazonaws.com/prod/get-data"
)
.then(response => {
const messages = response.data;
this.setState({ messages });
});
}
render() {
return (
<ul>
{this.messages}
Test
{this.state.messages.map(message => (
<li>{message}</li>
))}
</ul>
);
}
}
export default App;
A few points:
1) Change this.messages in ul of render method to this.state.messages, as this.messages is undefined.
2) A good practice while using JSX is to keep js and html code as distinguishable as possible, so the map on a list should be done outside the return statement.
const listItems = numbers.map((number) =>
<li>{number}</li>
);
return (
<ul>{listItems}</ul>
);
3) For more info about CORS error and how to rectify it while using AWS lambda, refer to this article which includes a code snippet: AWS: CORS