How to loop in render with array data API React - javascript

I have data from API where when I use console log I read all data.
When I want to rendering this data I see only the first index of the array.
API look like this:
aladinModel: (2) […]
​​
0: (48) […]
​​​
0: Object { DATS: "2019-10-20T23:00:00.000Z", TA: 12.1, RH: 93.3, … }
​​​
1: Object { DATS: "2019-10-21T02:00:00.000Z", TA: 11, RH: 95.1, … }
​​​
2: Object { DATS: "2019-10-21T05:00:00.000Z", TA: 12.4, RH: 96.5, … }
I want to display all values.
My code:
import React from "react";
export default class FetchRandomUser extends React.Component {
state = {
loading: true,
dataAPI: null
};
async componentDidMount() {
const url = "http://localhost:8000/?date=2019-10-26&station=1010&daysForward=5";
const response = await fetch(url);
const data = await response.json();
console.log(data);
this.setState({ dataAPI: data.aladinModel[0], loading: false });
}
render() {
if (this.state.loading) {
return <div>loading...</div>;
}
if (!this.state.dataAPI) {
return <div>Няма данни !</div>;
}
return (
<div>
<div>{this.state.dataAPI[0].DATS}</div>
</div>
);
}
}

constructor(props) {
super(props);
this.state = {
loading: true,
dataAPI: null
};
}
async componentDidMount() {
fetch("http://localhost:8000/?date=2019-10-26&station=1010&daysForward=5")
.then(response => response.json())
.then(data => {
return data;
})
.catch(error => console.log(error));
this.setState({ dataAPI: this.data, loading: false });
}
render() {
if (this.state.loading) {
return <div>loading...</div>;
}
if (!this.state.dataAPI) {
return <div>Няма данни !</div>;
}
return this.state.dataAPI.map((data, i) => (
<div key={i}>
{data.DATS},{data.TA},{data.RH}
</div>
));
}

Related

setState() in componentDidMount() - When is the intermediate state REALLY noticeable TO THE USER?

The React doc states that the intermediate state will not be shown to the user, but why in this example it does show "loading...." (the intermediate state in this case)?
You may call setState() immediately in componentDidMount(). It will
trigger an extra rendering, but it will happen before the browser
updates the screen. This guarantees that even though the render() will
be called twice in this case, the user won’t see the intermediate
state.
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
error: null,
isLoaded: false,
items: []
};
}
componentDidMount() {
fetch("https://jsonplaceholder.typicode.com/posts")
.then(res => res.json())
.then(
(result) => {
this.setState({
isLoaded: true,
items: result
});
},
// Note: it's important to handle errors here
// instead of a catch() block so that we don't swallow
// exceptions from actual bugs in components.
(error) => {
this.setState({
isLoaded: true,
error
});
}
)
}
render() {
const { error, isLoaded, items } = this.state;
if (error) {
return <div>Error: {error.message}</div>;
} else if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<ul>
{items.map(item => (
<li key={item.id}>
{item.userId} - {item.title}
</li>
))}
</ul>
);
}
}
}
When I do not use AJAX calls the intermediate state is not seen ("loading...) for example:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
error: null,
isLoaded: false,
items: []
};
}
componentDidMount() {
this.setState({
isLoaded: true,
items: [
{ "id": 1, "name": "Apples", "price": "$2" },
{ "id": 2, "name": "Peaches", "price": "$5" }
]
});
}
render() {
const { error, isLoaded, items } = this.state;
if (error) {
return <div>Error: {error.message}</div>;
} else if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<ul>
{items.map(item => (
<li key={item.id}>
{item.id} - {item.name}
</li>
))}
</ul>
);
}
}
}
Because in the first example, you're not calling setState immediately in componentDidMount().
You're calling it from a function the asynchronous fetch() invocation (eventually) calls.

Reac js TypeError: this.state.data.map is not a function

class CardList extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
};
}
componentDidMount() {
firestore
.collection('users')
.get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
this.setState({ data: doc.data() });
});
});
}
render() {
return (
<div className="cardlist">
{this.state.data.email
? this.state.data.map((data) => {
return <div>{this.state.data.email}</div>;
})
: console.log('error')}
</div>
);
}
}
TypeError: this.state.data.map is not a function
I want to take out the emails in the Firestore and print them out, but I can't print them because of typeerror. Why is there an error?
console.log(this.state.data) result is
{ createdAt: t, name: 'good', email: 'good#gmail.com', isTutor: 'off' };
{ name: 'joe', isTutor: 'on', email: 'joe#gmail.com', createdAt: t };
You are not assigning value to your array properly, rather you should do like the code below. I've also refactored the code in render function.
class CardList extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
};
}
componentDidMount() {
firestore
.collection('users')
.get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
this.setState({ data: [...this.state.data, doc.data()] });
});
});
}
render() {
return (
<div className="cardlist">
{this.state.data &&
this.state.data.map((item) => {
return <div>{item.email}</div>;
})}
</div>
);
}
}
this.setState({ data: doc.data() }); - you are not adding to the state, but replacing it with an object for each doc. And you cannot .map an object, thus the error.

Pass props to another component and redraw the page

In 1 component, when I click on the picture, I get its id, which I pass to another component via props. I need to receive these props every time and send a feth - request with the id of the image and then redraw the component. How to do it correctly?
first component
export default class Home extends Component {
constructor(props) {
super(props);
this.state = {
error: null,
isLoaded: false,
isOpen: false,
images: [],
idImg: ''
};
}
openModal = (e) => {
this.setState({ isOpen: true, idImg: e.target.id });
}
render() {
const {error, isLoaded, images} = this.state;
if (error) {
return <p>Error</p>
} else if (!isLoaded) {
return <p> Loading ... </p>
} else {
return (
<div className="row align-items-center m-4" onChange={this.onSelect}>
<Modal
isOpen={this.state.isOpen}
onCancel={this.handleCancel}
onSubmit={this.handleSubmit}
idImg={this.state.idImg}
></Modal>
{images.map(item => (
<div key={item.image_id} className="col-lg-4 col-lg-4 sm-1 p-2" style={{Style}} >
<img id={item.image_id} src={item.src} alt={item.src} onClick={this.openModal}></img>
</div>
))}
</div>
)
}
}
2 component:
export default class Modal extends Component {
constructor(props){
super(props);
this.state = {
imgSrc: ' ',
commentList: [],
_id: this.props.idImg
}
}
componentDidMount(){
fetch(`./api/${this.state._id}`, {
method: 'GET',
})
.then(res => res.json())
.then((result) => {
this.setState({
isLoaded: true,
imgSrc: result.src
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
);
Factor out the fetch into a utility function that can be called in componentDidMount and componentDidUpdate when the props update.
Also, don't store passed props into local component state, this is an anti-pattern in react. You can simply consume the passed idImg prop in the lifecycle methods.
export default class Modal extends Component {
constructor(props){
super(props);
this.state = {
imgSrc: ' ',
commentList: [],
}
}
fetchImage = imageId => {
this.setState({ isLoaded: false }); // <-- set loading state
fetch(`./api/${imageId}`, {
method: 'GET',
})
.then(res => res.json())
.then((result) => {
this.setState({
isLoaded: true,
imgSrc: result.src
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
);
};
componentDidMount() {
this.fetchImage(this.props.idImg); // <-- pass idImg prop
}
componentDidUpdate(prevProps) {
if (prevProps.idImg !== this.props.idImg) { // <-- compare idImg values
this.fetchImage(this.props.idImg); // <-- pass idImg prop
}
}
export default class Modal extends Component {
constructor(props){
super(props);
this.state = {
imgSrc: ' ',
commentList: [],
_id: this.props.idImg
}
this.nameFunction=this.nameFunction.bind(this);
}
componentDidMount(){
this.nameFunction();
}
componentDidUpdate(prevProps) {
if (prevProps.idImg!== this.props.idImg) {
this.setState({
_id: this.props.idImg,
})
}
}
nameFunction(){
fetch(`./api/${this.state._id}`, {
method: 'GET',
})
.then(res => res.json())
.then((result) => {
this.setState({
isLoaded: true,
imgSrc: result.src
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
);
}

In React app , I delete my component data on firebase but it does'n delete from my dom even when I change the state

I have get my data from firebase , loop through them and display them to dom.
then I added a delete button and send a delete request using axios and it's delete from firebase but the dom doesn't rerender. I set a deleting state to change it in 'then' block but even when I change the state it dosn't rerender!
what can I do?
class Orders extends Component {
state = {
orders: [],
loading: true,
deleting: false,
};
componentDidMount() {
axios
.get('/order.json')
.then((res) => {
// console.log(res.data);
const fetchedOrders = [];
for (let key in res.data) {
fetchedOrders.push({ ...res.data[key], id: key });
}
this.setState({ loading: false, orders: fetchedOrders });
})
.catch((err) => {
this.setState({ loading: false });
});
}
deleteHandler = (id) => {
axios.delete(`/order/${id}.json`).then((res) => {
this.setState({ deleting: true });
console.log(res, this.state.deleting);
});
};
render() {
return (
<div>
{this.state.orders.map((order) => (
<Order
key={order.id}
ingredients={order.ingredient}
price={order.price}
id={order.id}
delete={() => this.deleteHandler(order.id)}
/>
))}
</div>
);
}
}
You have to update the orders state while calling deleteHandler! Try this code!
import React from 'react';
import axios from 'axios';
// YOUR OTHER IMPORT GOES HERE
class Orders extends Component {
constructor(props) {
this.state = {
orders: [],
loading: true,
deleting: false,
}
}
componentDidMount() {
axios
.get('/order.json')
.then((res) => {
// console.log(res.data);
const fetchedOrders = [];
for (let key in res.data) {
fetchedOrders.push({ ...res.data[key], id: key });
}
this.setState({ loading: false, orders: fetchedOrders });
})
.catch((err) => {
this.setState({ loading: false });
});
}
deleteHandler = (id) => {
this.setState({
orders: this.state.orders.filter(orderValue => orderValue.id !== id)
})
axios.delete(`/order/${id}.json`).then((res) => {
this.setState({ deleting: true });
console.log(res, this.state.deleting);
});
};
render() {
return (
<div>
{this.state.orders.map((order) => (
<Order
key={order.id}
ingredients={order.ingredient}
price={order.price}
id={order.id}
delete={() => this.deleteHandler(order.id)}
/>
))}
</div>
);
}
}

map is not a function in react

I've been trying for three days to solve that I can not put several elements in an array,but if I can put only one When I put in the return this.state.dat.nombre or dat.carrera it works, but if I try to put with the map function I do not get
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
dat: [],
isFetch: true
};
}
componentDidMount() {
var url =
"https://cors-anywhere.herokuapp.com/http://sipla.cuci.udg.mx/sc/horariop.php?c=219359735&k=0d8ce4fab5f4df9ce711cae81e044e1a";
fetch(url, {
method: "GET",
headers: {
"X-Requested-With": "XMLHttpRequest"
}
})
.then(response => {
return response.json();
})
.then(art => {
this.setState({ dat: art, isFetch: false });
});
}
render() {
if (this.state.isFetch) {
return "cargando....";
}
this.state.dat.map(art => {
return (
<tr key={art.codigo}>
<td>{art.nombre}</td>
<td>{art.carrera}</td>
<td>{art.horarios}</td>
</tr>
);
});
}
}
export default App;
When I checked your API, I got this data
{
carrera: "INGENIERIA EN COMPUTACION"
ciclo_ingreso: "2019A"
clave_carrera: "INCO"
codigo: "219359735"
cu: "CENTRO UNIVERSITARIO DE LA CIENEGA"
estatus: "ACTIVO"
fecha_consulta: "2019-07-12 12:20:20"
horarios: (4) [{…}, {…}, {…}, {…}]
nivel: "LICENCIATURA"
nombre: "MARIA CECILIA PEREZ PEREZ"
sede: "CAMPUS OCOTLAN"
ultimo_ciclo: "2019B"
}
This is not array. map function for array.
If you want to use this data, you can just write like this.
render() {
if(this.state.isFetch){
return 'cargando....'
}
const {dat} = this.state;
return (
<tr key={dat.codigo}>
<td>{dat.nombre}</td>
<td>{dat.carrera}</td>
<td>{dat.horarios}</td>
</tr>
);
}
Just copy this code and run, you will get desired answer
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
dat: [],
isFetch: true
};
}
componentDidMount() {
let dat = []
var url =
"https://cors-anywhere.herokuapp.com/http://sipla.cuci.udg.mx/sc/horariop.php?c=219359735&k=0d8ce4fab5f4df9ce711cae81e044e1a";
fetch(url, {
method: "GET",
headers: {
"X-Requested-With": "XMLHttpRequest"
}
})
.then(response => {
return response.json();
})
.then(art => {
dat.push(art)
this.setState({ dat, isFetch: false });
});
}
render() {
if (this.state.isFetch) {
return "cargando....";
}
this.state.dat.map(art => {
return (
<tr key={art.codigo}>
<td>{art.nombre}</td>
<td>{art.carrera}</td>
<td>{art.horarios}</td>
</tr>
);
});
}
}
export default App;```

Categories

Resources