Ich versuche, Daten aus Open Data abzurufen, um eine schnelle Heatmap zusammenzustellen. Dabei möchte ich einige Statistiken hinzufügen. Fast alles läuft gut, da ich die Daten habe und die Karte rendern kann, aber ich bin mir nicht sicher, wie ich mit Berechnungen umgehen soll, wenn ich die Daten erhalte, da es einige Zeit dauert, bis Daten eingehen. Wie richte ich die Dinge so ein? Ich kann eine Funktion für eine Statusvariable ausführen, wenn sie noch nicht unbedingt Daten empfangen hat. Derzeit erhalte ich eine Null als Nummer, die als Requisiten an StatCard übergeben wird.
Unten sind meine Versuche:
App.js.
import React, { Component } from 'react';
import Leaf from './Leaf';
import Dates from './Dates';
import StatCard from './StatCard';
import classes from './app.module.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {
data:[],
cleanData:[],
dateInput: '2019-10-01',
loading: false,
totalInspections: null,
calculate: false
};
}
componentDidMount() {
try {
this.fetchData();
} catch (err) {
console.log(err);
this.setState({
loading: false
})
}
}
fetchData=()=>{
const requestData = async () => {
await fetch(`https://data.cityofnewyork.us/resource/p937-wjvj.json?$where=latitude > 39 AND latitude< 45 AND inspection_date >= '${this.state.dateInput}'&$limit=50000`)
.then(res => res.json())
.then(res =>
//console.log(res)
this.setState({ data: res, loading: true})
)
}
const calculateInspections = () => {
this.setState({totalInspections: this.state.data.length})
}
//call the function
requestData();
if(this.state.data) {
calculateInspections();
}
}
handleDateInput = (e) => {
console.log(e.target.value);
this.setState({dateInput:e.target.value, loading: false}) //update state with the new date value
this.updateData();
//this.processGraph(e.target.value)
}
updateData =() => {
this.fetchData();
}
LoadingMessage=()=> {
return (
<div className={classes.splash_screen}>
<div className={classes.loader}></div>
</div>
);
}
//inspection_date >= '${this.state.dateInput}'&
// https://data.cityofnewyork.us/resource/p937-wjvj.json?$where=inspection_date >= '2019-10-10T12:00:00'
render() {
return (
<div>
<div>{!this.state.loading ?
this.LoadingMessage() :
<div></div>}
</div>
{this.state.totalInspections && <StatCard totalInspections={this.state.totalInspections} /> }
<Dates handleDateInput={this.handleDateInput}/>
<Leaf data={this.state.data} />
</div>
);
}
}
export default App;
StatCard.js
import React from 'react';
const StatCard = ( props ) => {
return (
<div >
{ `Total Inspections: ${props.totalInspections}`}
</div>
)
};
export default StatCard;
Reparaturversuch
componentDidMount() {
try {
this.fetchData();
} catch (err) {
console.log(err);
this.setState({
loading: false
})
}
}
componentDidUpdate () {
if(this.state.data) {
this.setState({totalInspections: this.state.data.length})
}
}
fetchData= async ()=>{
const requestData = () => {
fetch(`https://data.cityofnewyork.us/resource/p937-wjvj.json?$where=latitude > 39 AND latitude< 45 AND inspection_date >= '${this.state.dateInput}'&$limit=50000`)
.then(res => res.json())
.then(res =>
//console.log(res)
this.setState({ data: res, loading: true})
)
}
//call the function
await requestData();
}
javascript
reactjs
fetch
react-props
LoF10
quelle
quelle
this.setState({ data: res, loading: true})
ein Tippfehler in derrequestData
Funktion? sollte nichtloading
eingestellt werden,false
wenn die Daten abgerufen werden?Antworten:
Rendern
<StatCard />
Sie nur, wenn Sie die Daten haben, die Sie benötigen:quelle
await requestData()
es nicht direkt zur Funktion requestData hinzufügen und hinzufügenasync fetchData = () => {}
. Besser noch,fetchData
sollte nur die Daten abrufen und im Zustand speichern. Dann sollten Sie verwendencomponentDidUpdate
, umcalculateInspections()
nur beithis.state.data
Änderungen auszulösenZunächst glaube ich nicht, dass Sie eine separate Funktion benötigen
calculateInspections()
. Sie können diese Logik in denthen
Rückruf einfügen.Zweitens ist die Einstellung
this.state.totalInspections
effektiv redundant, da Sie einfach Folgendes tun können:Schließlich vermeiden , mit
componentDidUpdate()
Haken , wenn Sie neu zu reagieren. Meistens schießt du dir in den Fuß.Derzeit hat Sie Ihre Reparaturversuche gerade in eine Endlos-Render-Schleife gebracht. Dies geschieht, weil bei jedem Aufruf nach dem Rendern der Lifecycle-Hook
setState()
aufgerufen wirdcomponentDidUpdate()
. Aber innerhalbcomponentDidUpdate()
Ihres Anrufs wird erneut angerufensetState()
, wodurch ein Folgeanruf für denselben Lebenszyklus-Hook ausgelöst wird, und somit geht die Schleife weiter und weiter.Wenn Sie die Faustregel verwenden
componentDidUpdate()
und nachsetState()
innen rufen müssen , stellen Sie immer eine Stoppbedingung vor. In Ihrem Fall wird es sein:quelle
Ihr Problem ist also, dass der Status isLoading vor asynchronen Aufrufen SYNCHRON gesetzt werden muss.
Also in Ihrem componentDidMount:
Dies stellt das Laden sicher, sobald Sie den Anruf tätigen. Dann wird Ihr Anruf getätigt und dieser Teil ist ASYNCHRON. Sobald die Daten eingehen, ist das Laden abgeschlossen
Darüber hinaus: Ihre Render-Methode kann mehrere return-Anweisungen haben. Geben Sie anstelle von bedingtem jsx Ihr Ladelayout zurück
quelle
Hier ist meine Lösung.
quelle