How to get a specific data from fetch api - javascript

I am trying to get and show a specific data from api in a <Text> tag in my React Native app.
What I'm trying to do is to show the name of second object from that api.
Here is my code :
class HomeSreen extends Component {
constructor(props) {
super(props);
this.state = {
dataSource: [],
};
}
componentDidMount() {
const request = new Request('http://jsonplaceholder.typicode.com/users');
fetch(request)
.then(response => response.json())
.then(responseJson => {
this.setState({
dataSource: responseJson,
});
});
}
render() {
return (
<View>
<Text>Home Screen</Text>
<Text>{this.state.dataSource[1].name}</Text>
</View>
);
}
}
And the API :
[
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere#april.biz",
"address": {
"street": "Kulas Light",
"suite": "Apt. 556",
"city": "Gwenborough",
"zipcode": "92998-3874",
"geo": {
"lat": "-37.3159",
"lng": "81.1496"
}
},
"phone": "1-770-736-8031 x56442",
"website": "hildegard.org",
"company": {
"name": "Romaguera-Crona",
"catchPhrase": "Multi-layered client-server neural-net",
"bs": "harness real-time e-markets"
}
},
{
"id": 2,
"name": "Ervin Howell",
"username": "Antonette",
"email": "Shanna#melissa.tv",
"address": {
"street": "Victor Plains",
"suite": "Suite 879",
"city": "Wisokyburgh",
"zipcode": "90566-7771",
"geo": {
"lat": "-43.9509",
"lng": "-34.4618"
}
},
"phone": "010-692-6593 x09125",
"website": "anastasia.net",
"company": {
"name": "Deckow-Crist",
"catchPhrase": "Proactive didactic contingency",
"bs": "synergize scalable supply-chains"
}
},
.
.
.
But I can't get the data I need.
Any help would be appreciated

these data requests asynchronously, so when the first render occurs, there is no data returned from the API.
class HomeSreen extends Component {
constructor(props) {
super(props);
this.state = {
dataSource: [],
};
}
componentDidMount() {
const request = new Request('http://jsonplaceholder.typicode.com/users');
fetch(request)
.then(response => response.json())
.then(responseJson => {
this.setState({
dataSource: responseJson,
});
});
}
render() {
return (
<View>
<Text>Home Screen</Text>
{
this.state.dataSource.length === 0 ?
<Text>Waiting moment.</Text> :
<Text>{this.state.dataSource[1].name}</Text>
}
</View>
);
}
}
Making these changes you can visualize the data you need.

If the problem is that your component isn't updating the that property after the request is complete it is because you are doing a 'shallow merge' on the dataSource Array so React isn't able to detect changes to the data. There are a few ways you can handle it:
Deep merge
fetch(request)
.then(response => response.json())
.then(responseJson => {
this.setState(prevState => {
return {
...prevState.dataSource,
dataSource: responseJson.map((obj, i)=>{ return {...dataSource[i], ...obj}},
}
});
});
https://reactjs.org/docs/optimizing-performance.html#shouldcomponentupdate-in-action
Pull the name property out to the top-level of you component state
class HomeSreen extends Component {
constructor(props) {
super(props);
this.state = {
dataSource: [],
screenTitle
};
}
componentDidMount() {
const request = new Request('http://jsonplaceholder.typicode.com/users');
fetch(request)
.then(response => response.json())
.then(responseJson => {
this.setState({
screenTitle: responseJson[1].name,
});
});
}
render() {
return (
<View>
<Text>Home Screen</Text>
<Text>{this.state.screenTitle}</Text>
</View>
);
}
}

Related

React table from object with objects

I got 2 types of json API and i want to display them in table. First one has following structure:
data1:[
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere#april.biz",
"address":"Gwenborough",
"phone": "1-770-736-8031 x56442",
"website": "hildegard.org",
"company": "Romaguera-Crona"
},
{
"id": 2,
"name": "Ervin Howell",
"username": "Antonette",
"email": "Shanna#melissa.tv",
"address": "Wisokyburgh",
"phone": "010-692-6593 x09125",
"website": "anastasia.net",
"company": "Deckow-Crist"
}
]
Second:
data2:[
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere#april.biz",
"address": {
"street": "Kulas Light",
"suite": "Apt. 556",
"city": "Gwenborough",
"zipcode": "92998-3874",
"geo": {
"lat": "-37.3159",
"lng": "81.1496"
}
},
"phone": "1-770-736-8031 x56442",
"website": "hildegard.org",
"company": {
"name": "Romaguera-Crona",
"catchPhrase": "Multi-layered client-server neural-net",
"bs": "harness real-time e-markets"
}
},
{
"id": 2,
"name": "Ervin Howell",
"username": "Antonette",
"email": "Shanna#melissa.tv",
"address": {
"street": "Victor Plains",
"suite": "Suite 879",
"city": "Wisokyburgh",
"zipcode": "90566-7771",
"geo": {
"lat": "-43.9509",
"lng": "-34.4618"
}
},
}
]
My Table component works for first type of data (data1) and creates a table. But obviously for second (data2) type i'm getting error. I tried a lot of things and i can't get access to address and geo fields and can't display them in table.
Table component:
export default class Table extends React.Component {
constructor(props){
super(props);
this.getHeader = this.getHeader.bind(this);
this.getRowsData = this.getRowsData.bind(this);
this.getKeys = this.getKeys.bind(this);
}
getKeys = function(){
return Object.keys(this.props.data[0]);
}
getHeader = function(){
var keys = this.getKeys();
return keys.map((key, index)=>{
return <th key={key}>{key.toUpperCase()}</th>
})
}
getRowsData = function(){
var items = this.props.data;
var keys = this.getKeys();
return items.map((row, index)=>{
return <tr key={index}><RenderRow key={index} data={row} keys={keys}/></tr>
})
}
render() {
console.log('Get keys:', this.getKeys());
return (
<div>
<table>
<thead>
<tr>{this.getHeader()}</tr>
</thead>
<tbody>
{this.getRowsData()}
</tbody>
</table>
</div>
);
}
}
const RenderRow = (props) =>{
return props.keys.map((key, index)=>{
return <td key={props.data[key]}>{props.data[key]}</td>
})
}
const uniqueArr = [...data1, ...data2]
const formatData = uniqueArr.map((item) => {
if(typeof item.address === "object"){
return {
...item,
address: item.address.street.concat(", ", item.address.city),
company: item.company ? item.company.name : ""
}
}
return item
})

How to get axios.post to update my API with Click button ? (Help)

My GET & POST Axios code:
import React, { useState, useEffect } from "react";
import { StyleSheet, Text, View, Image, ScrollView } from "react-native";
import Card from "../../molecules/Card";
import Button from "../../atoms/Button";
import Axios from "axios";
const HomeScreen = () => {
const [users, setUsers] = useState([]);
useEffect(() => {
//Fetch
// fetch('https://reqres.in/api/users')
// .then(res => res.json())
// .then(json => setUsers(json.data));
//Axios
Axios.get("http://localhost:3004/users").then((res) => setUsers(res.data));
}, [users]);
const handleSubmit = () => {
const data = {
email: "angelin.veronica#mail.com",
first_name: "Angelin",
last_name: "Veronica",
avatar: "https://reqres.in/img/faces/7-image.jpg",
};
Axios.post("http://localhost:3004/users", data);
};
return (
<View style={styles.container}>
<Text style={styles.title}> Home Screen </Text>
<ScrollView showsVerticalScrollIndicator={false}>
<Button label="Update" onSubmit={handleSubmit} />
{users.map((item) => (
<Card
key={item.id}
fullName={`${item.first_name} ${item.last_name}`}
// name={item.name}
// username={item.username}
email={item.email}
imageUrl={item.avatar}
// address={`${item.address.street}, ${item.address.suite}, ${item.address.city}, ${item.address.zipcode}`}
// phone={item.phone}
/>
))}
</ScrollView>
</View>
);
};
export default HomeScreen;
my API=
[
{
"id": 7,
"email": "michael.lawson#reqres.in",
"first_name": "Michael",
"last_name": "Lawson",
"avatar": "https://reqres.in/img/faces/7-image.jpg"
},
{
"id": 8,
"email": "lindsay.ferguson#reqres.in",
"first_name": "Lindsay",
"last_name": "Ferguson",
"avatar": "https://reqres.in/img/faces/8-image.jpg"
},
{
"id": 9,
"email": "tobias.funke#reqres.in",
"first_name": "Tobias",
"last_name": "Funke",
"avatar": "https://reqres.in/img/faces/9-image.jpg"
},
{
"id": 10,
"email": "byron.fields#reqres.in",
"first_name": "Byron",
"last_name": "Fields",
"avatar": "https://reqres.in/img/faces/10-image.jpg"
},
{
"id": 11,
"email": "george.edwards#reqres.in",
"first_name": "George",
"last_name": "Edwards",
"avatar": "https://reqres.in/img/faces/11-image.jpg"
},
{
"id": 12,
"email": "rachel.howell#reqres.in",
"first_name": "Rachel",
"last_name": "Howell",
"avatar": "https://reqres.in/img/faces/12-image.jpg"
},
{
"id": 13,
"email": "maestro.pythagoras#gmail.com",
"first_name": "Maestro",
"last_name": "Pythagoras",
"avatar": "https://reqres.in/img/faces/10-image.jpg"
}
]
HELP: I can access the API and retrieve data from my local API, but when made the button, I don't know where the error is, because when I did an update on the button, my API was not updated at all, can someone help me in solving this problem, Thank you in advance.

How to use selected value in React dropdown as api url id?

I want to render into table specific data from url with id taken after user select the needed value so here is my code:
fetching data for select options:
export default function Dashboard() {
const [value, setValue] = useState();
const [students, setstudents] = useState([]);
useEffect(() => {
const fetchStudents = async () => {
try {
const resp = await Axios({
method: "GET",
url: "https://jsonplaceholder.typicode.com/users",
headers: {
"Content-Type": "application/json",
},
});
setstudents(resp.data);
} catch (err) {}
};
fetchStudents();
}, []);
const classes = useStyles();
const [selected,setselected]=useState();
const options = students.map(s => ({
"value" : s.id,
"label" : s.username
}))
const handleChange = (event) => {
setselected(event.value);
};
now fetching data in dashboard function for selected value:
const [tabl, settabl] = useState([]);
useEffect(() => {
const fetchtabl = async () => {
try {
const resp = await Axios({
method: "GET",
url: "https://jsonplaceholder.typicode.com/users"+{selected},
headers: {
"Content-Type": "application/json",
},
});
settabl(resp.data.surveys);
} catch (err) {
console.log(err);
}
};
fetchtabl();
}, []);
const getTableData = (tabl) => {
return tabl.map((tab) => [
tab.id,
tab.name,
tab.username,
]);
};
now render data in return:
Select the course:
<Select options={options} onChange={handleChange}/>
<Table
tableHead={["Course Code", "Course Name", "Survey Link"]}
tableData={getTableData(tabl)}
tableHeaderColor="primary"
/>
but nothing appear after select the value needed how can i fix it and does react allow to use selected value like this?
data
[
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere#april.biz",
"address": {
"street": "Kulas Light",
"suite": "Apt. 556",
"city": "Gwenborough",
"zipcode": "92998-3874",
"geo": {
"lat": "-37.3159",
"lng": "81.1496"
}
},
"phone": "1-770-736-8031 x56442",
"website": "hildegard.org",
"company": {
"name": "Romaguera-Crona",
"catchPhrase": "Multi-layered client-server neural-net",
"bs": "harness real-time e-markets"
}
},
{
"id": 2,
"name": "Ervin Howell",
"username": "Antonette",
"email": "Shanna#melissa.tv",
"address": {
"street": "Victor Plains",
"suite": "Suite 879",
"city": "Wisokyburgh",
"zipcode": "90566-7771",
"geo": {
"lat": "-43.9509",
"lng": "-34.4618"
}
},
"phone": "010-692-6593 x09125",
"website": "anastasia.net",
"company": {
"name": "Deckow-Crist",
"catchPhrase": "Proactive didactic contingency",
"bs": "synergize scalable supply-chains"
}
},
{
"id": 3,
"name": "Clementine Bauch",
"username": "Samantha",
"email": "Nathan#yesenia.net",
"address": {
"street": "Douglas Extension",
"suite": "Suite 847",
"city": "McKenziehaven",
"zipcode": "59590-4157",
"geo": {
"lat": "-68.6102",
"lng": "-47.0653"
}
},
"phone": "1-463-123-4447",
"website": "ramiro.info",
"company": {
"name": "Romaguera-Jacobson",
"catchPhrase": "Face to face bifurcated interface",
"bs": "e-enable strategic applications"
}
},
So based on the conversation in the comment section the value is there in selected. Then the only problem is useEffect is not triggered on change because of empty dependency array.
I suggest few modifications in your code:
Add to the dependency array selected as [selected] which will trigger the function once you have change on that state.
Check for null or undefined values in order not to concatenate without value.
Also I added one extra slash into your URL after users so now it's users/.
So the URL would be at the end of the day:
`https://jsonplaceholder.typicode.com/users/${selected}`
Based on the explanation try as:
useEffect(() => {
const fetchtabl = async () => {
try {
const resp = await Axios({
method: "GET",
url: `https://jsonplaceholder.typicode.com/users/${selected}`,
headers: {
"Content-Type": "application/json",
},
});
settabl(resp.data.surveys);
} catch (err) {
console.log(err);
}
};
if (selected) {
fetchtabl();
}
}, [selected]);
+1 suggestion:
Maybe it's not related but you have in .map() an extra [] which might be not needed, so try as:
const getTableData = (tabl) => {
return tabl.map((tab) => ({
tab.id,
tab.name,
tab.username,
}));
};
In this way .map() will return an array of objects with the properties of id, name, username.

Trying to render data on from database on page REACT

I'm finally not getting any errors, but now I can't get the data coming in from my database to render on the page
Here is the trouble component:
import React, { Component } from 'react';
import axios from 'axios';
export default class ListPets extends Component {
constructor(props) {
super(props);
this.state = {
pets: {},
isLoaded: false,
}
}
componentDidMount = () => {
This. getPets ();
};
getPets = async () => {
const res = await axios.get('http://localhost:5000/pets');
const pets = res.data;
this.setState({ isLoaded: true, pets });
console.log('Data has been received!');
}
render() {
console.log('State: ', this.state);
const { isLoaded, pets } = this.state;
if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div>
<ul>
{Object.entries(pets).map(([key, pet]) => (
<li key={key}>{pet.name}</li>
))}
</ul>
</div>
);
}
}
}
Here is the data I'm trying to render from my database
{
"_id": "5dfe7b55a3678700785c9b69",
"species": "Collie",
"name": "Dax",
"age": "2",
"petImage": "C:\\fakepath\\brown-and-white-dog-4633734_640.jpg"
}
{
"_id": "5dfe828af33fa800ac8b49c8",
"species": "lab",
"name": "bea",
"age": "1",
"petImage": "C:\\fakepath\\puppy-1207816_640.jpg"
}
{
"_id": "5dfea025ea5cc2016e528f5a",
"species": "pittbull",
"name": "nina",
"age": "3",
"petImage": "C:\\fakepath\\pitbull1.jpg"
}
{
"_id": "5dfea0c229d0d4017b982f35",
"species": "pittbull",
"name": "nina",
"age": "3",
"petImage": "C:\\fakepath\\pitbull1.jpg"
}
{
"_id": "5dfea63eb1505e018a2ba363",
"species": "pittbull",
"name": "Gina",
"age": "3",
"petImage": "C:\\fakepath\\pitbull1.jpg"
}
{
"_id": "5dfea7a1fed64001b9632b8f",
"species": "pittbull",
"name": "kat",
"age": "2",
"petImage": "C:\\fakepath\\pitbull1.jpg"
}
If you are getting the data use the state
return (
<div>
<ul>
{this.state.pets.map(pet => (
<li key={pet.id}>{pet.name}</li>
))}
</ul>
</div>
);
}
}
}

I can not get data from this.state

I receive JSON from my back end, I save it in my state and I want to use it in props in another react component, but it doesn't work.
I try to show need date like that in props of my component - {this.state.movies["0"]["title"]}, but it doesn't work.
constructor() {
super();
this.state = {
movies: []
}
}
componentDidMount() {
this.getAllMoviesForMainPage();
}
getAllMoviesForMainPage() {
axios.get("http://localhost:8080/showAll")
.then(response => {
this.setState({ movies: response.data })
})
}
render() {
return (
<div className="qwerty">
<MainPageComponent />
<div className='moviePreviewGrid'>
<Router>
<div className="moviePreviewGrid-row">
<div className="moviePreviewGrid-col">
<MoviePreview
Title={this.state.movies["2"]["title"]}
MoviePreviewAvatar={DrivePoster}
SeeMore="unrelated long string here"
/>
<NavLink to="/showByTitle/Драйв">
<button type="button" className="myBtn">See more</button>
</NavLink>
</div>
and structure of my JSON
[
{
"id": 1,
"title": "Джокер",
"releaseDate": "2019",
"genre": "Триллер, драма, криминал",
"duration": "122 минуты",
"rating": 8.7,
"criticReviews": [
{
"criticName": "Anton",
"review": "anton review"
},
{
"criticName": "OldCritic",
"review": "old review"
}
],
"userReviews": [
{
"nickName": "Igor",
"review": "igor review"
},
{
"nickName": "Nik",
"review": "nik review"
}
]
},
{
"id": 2,
"title": "Ирландец",
"releaseDate": "2019",
"genre": "Драма, триллер, криминал, биографический",
"duration": "209 минут",
"rating": 8.4,
"criticReviews": [
{
"criticName": "YoungCritic",
"review": "young review"
}
],
"userReviews": [
{
"nickName": "Gambit",
"review": "gambit review"
},
{
"nickName": "Andrew",
"review": "andrew review"
}
]
},
{
"id": 3,
"title": "Драйв",
"releaseDate": "2011",
"genre": "Боевик, драма",
"duration": "100 минут",
"rating": 7.8,
"criticReviews": [
{
"criticName": "Critic",
"review": "review"
}
],
"userReviews": [
{
"nickName": "Anton",
"review": "anton review"
}
]
},
{
"id": 4,
"title": "Последний человек на Земле",
"releaseDate": "2015",
"genre": "Комедия",
"duration": "22 минуты",
"rating": 7.3,
"criticReviews": [
{
"criticName": "NewCritic",
"review": "new review"
}
],
"userReviews": [
{
"nickName": "Atomf7",
"review": "atomf7 review"
}
]
},
{
"id": 5,
"title": "Интерстеллар",
"releaseDate": "2014",
"genre": "Фантастика, драма, приключения",
"duration": "169 минут",
"rating": 8.6,
"criticReviews": [
{
"criticName": "Nik",
"review": "nik review"
}
],
"userReviews": [
{
"nickName": "Alice",
"review": "alice review"
}
]
}
]
and i wont to have for example title of first movie
In the first init, the this.state.movies has a length of 0 so this.state.movies["2"]["title"] of course would have no value at all
because getAllMoviesForMainPage is async (axios call) and takes a little longer to complete, so first you must give it an initial value and only when the request completes you can give it the real value.
example:
<MoviePreview
Title={this.state.movies.length > 0 ? this.state.movies[2].title : ""}
MoviePreviewAvatar={DrivePoster}
/>
Usually a state, isLoading is used for this case. So you can know when you received your data.
In the first render movies are not already fetched from the api.
So you need to conditionally render it.
import React, { Component } from "react";
import axios from "axios";
export default class Test extends Component {
constructor() {
super();
this.state = {
movies: [],
loading: true
}
}
componentDidMount() {
this.getAllMoviesForMainPage();
}
getAllMoviesForMainPage() {
axios.get("http://localhost:8080/showAll")
.then(response => {
this.setState({ movies: response.data, loading: false })
})
}
render() {
const { loading, movies } = this.state;
if (loading) {
return <div>Loading...</div>;
} else {
return (
<div>
{movies.length > 0 ? (
<div>First movie title: {movies[0].title}</div>
) : (
<div>No movies</div>
)}
</div>
);
}
}
}
You can check this example using a fake api.
You are making a GET request in componentDidMount which is async so until the promise is resolve in .then(.. your state does not contain response.data in movies.
The important thing to remember is component gets re-render every time you do this.setState(.. , so before you do setState in your getAllMoviesForMainPage method, the initial render will happen and it will contain an empty array in this.state.movies that you have defined in constructor
Also since your response contains array of objects, you would be using movies['2'].title instead of movies['2']['title']
So your render method should contain something like this to show movie preview:
<div className="moviePreviewGrid-col">
{this.state.movies.length ? (
<MoviePreview
Title={this.state.movies['2'].title}
MoviePreviewAvatar={DrivePoster}
SeeMore="unrelated long string here"
/>
) : (
<PlaceHolderPreview />
)}
<NavLink to="/showByTitle/Драйв">
<button type="button" className="myBtn">
See more
</button>
</NavLink>
</div>
PlaceHolderPreview can be your another component that will show -- well a placeholder for preview.
Hope it all makes sense.

Categories