Estoy intentando extraer datos de Open Data para armar un mapa de calor rápido. En el proceso quiero agregar algunas estadísticas. Casi todo funciona bien porque tengo los datos y soy capaz de representar el mapa, pero no estoy seguro de cómo manejar los cálculos una vez que obtengo los datos, ya que lleva tiempo ingresarlos. ¿Cómo configuro las cosas para que ¿Puedo ejecutar una función en una variable de estado si aún no ha recibido necesariamente los datos? Actualmente obtengo un valor nulo como el número que se pasa como accesorios a StatCard.
A continuación están mis intentos:
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;
Intento de reparación
   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
fuente
                
                fuente

this.setState({ data: res, loading: true})un error tipográfico en larequestDatafunción? noloadingdebería establecerse enfalsecuando se obtienen los datos?Respuestas:
Solo renderice
<StatCard />si tiene los datos que necesita:fuente
await requestData()lugar de agregarlo directamente a la función requestData y agregarasync fetchData = () => {}. Mejor aún,fetchDatasolo debe buscar los datos y almacenarlos en estado. Entonces debería usarcomponentDidUpdatepara dispararcalculateInspections()solo cuando losthis.state.datacambiosEn primer lugar , no creo que necesites una función separada
calculateInspections(). Puede poner esa lógica en lathendevolución de llamada.En segundo lugar , la configuración
this.state.totalInspectionses efectivamente redundante, ya que puede hacer:Por último, evite usar el
componentDidUpdate()gancho cuando sea nuevo en reaccionar. La mayoría de las veces terminas disparándote en el pie.Actualmente, su intento de reparación acaba de meterlo en un bucle de renderizado infinito. Esto sucede porque cada vez que llama
setState(), llamará acomponentDidUpdate()gancho de ciclo de vida después de la representación. Pero dentro decomponentDidUpdate()usted vuelve a llamarsetState(), lo que induce una llamada de seguimiento al mismo enlace de ciclo de vida, y por lo tanto, el ciclo continúa.Si debe usar
componentDidUpdate()y llamar alsetState()interior, regla general, siempre coloque una condición de detención por delante. En tu caso, será:fuente
Entonces, su problema es que el estado de carga debe establecerse SINCRÓNICAMENTE antes de cualquier llamada asíncrona.
Entonces, en su componenteDidMount:
Esto garantiza la carga tan pronto como realice la llamada. Luego se realiza su llamada y esa parte es ASINCRÓNICA. Tan pronto como los datos lleguen, la carga estará lista.
Más aún: su método de representación puede tener múltiples declaraciones de retorno En lugar de tener jsx condicional, devuelva su diseño de carga
fuente
Aquí está mi solución.
fuente