Làm thế nào để đúng thời gian kết xuất dữ liệu trong phản ứng?


8

Tôi đang cố gắng kéo dữ liệu từ Dữ liệu mở để đưa ra một bản đồ nhiệt nhanh. Trong quá trình tôi muốn thêm một số số liệu thống kê. Hầu như mọi thứ đều chạy tốt trong đó tôi có dữ liệu và có thể hiển thị bản đồ, nhưng tôi không chắc chắn làm thế nào để xử lý các tính toán một khi tôi nhận được dữ liệu vì phải mất thời gian để dữ liệu vào. Làm cách nào để thiết lập mọi thứ Tôi có thể chạy một hàm trên một biến trạng thái nếu nó chưa nhất thiết phải nhận dữ liệu? Hiện tại tôi đang nhận được một số không là số được chuyển làm đạo cụ cho StatCard.

Dưới đây là những nỗ lực của tôi:

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;

Cố gắng sửa chữa

   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();

  }

this.setState({ data: res, loading: true})một lỗi đánh máy trong requestDatachức năng? không nên loadingđược đặt thành falsekhi dữ liệu được tìm nạp?
Junaskell

vâng, đó là một lỗi đánh máy
LoF10

Bạn có chắc chắn việc sử dụng các tham số truy vấn tương ứng với tài liệu API không?
Jurrian

Có, như bạn có thể thấy trong mã dữ liệu được tìm nạp, đó không phải là vấn đề. Tôi có dữ liệu. Vấn đề là tôi không chắc chắn nên chạy tính toán ở đâu và khi nào vì nó cần chạy khi tôi đã nhận được tất cả dữ liệu API và sau đó được chuyển làm đạo cụ cho statCard.
LoF10

Vui lòng gửi cho tôi liên kết
mã và hộp

Câu trả lời:


0

Chỉ kết xuất <StatCard />nếu bạn có dữ liệu bạn cần:

{this.state.totalInspections && <StatCard totalInspections={this.state.totalInspections} /> }

Tôi đã thử điều đó nhưng không có xúc xắc. Cũng đã cố chạy tính toán chỉ khi this.state.data tồn tại trong thành phầnDidMount nhưng không gặp may. Những gì tôi nhận được bây giờ chỉ là số 0 là StatCard sẽ là
LoF10

1
Tôi hiểu rồi, đó là vì bạn không hiểu cách thức hoạt động của lời hứa / async. Bạn cần await requestData()thay vì thêm nó trực tiếp vào hàm requestData và thêm async fetchData = () => {}. Tốt hơn hết, fetchDatachỉ nên lấy dữ liệu và lưu trữ ở trạng thái. Sau đó, bạn chỉ nên sử dụng componentDidUpdateđể kích hoạt calculateInspections()khi this.state.datathay đổi
Chase DeAnda

Này Chase, cố gắng vận hành những gì bạn đã chỉ ra, mặc dù tôi thừa nhận tôi vẫn đang học nên không biết chính xác cách thực hiện. tôi đã thêm nỗ lực của mình vào câu hỏi của tôi nếu bạn có thể xem và chỉ cho tôi đi đúng hướng?
LoF10

0

Trước hết , tôi không nghĩ bạn cần một chức năng riêng biệt calculateInspections(). Bạn có thể đặt logic đó trong cuộc thengọi lại.

fetchData = () => {
  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(data => {
      this.setState({
        data: data,
        loading: true,
        totalInspections: this.state.data.length
      })
    })
}

Thứ hai , cài đặt this.state.totalInspectionscó hiệu quả dự phòng, vì bạn có thể đơn giản thực hiện:

{this.state.data && <StatCard totalInspections={this.state.data.length} /> }

Cuối cùng, tránh sử dụng componentDidUpdate()hook khi bạn mới phản ứng. Hầu hết thời gian bạn sẽ tự bắn vào chân mình.

Hiện tại Cố gắng sửa chữa của bạn đã đưa bạn vào một vòng lặp kết xuất vô hạn. Điều này xảy ra bởi vì bất cứ khi nào bạn gọi setState(), nó sẽ gọi componentDidUpdate()móc vòng đời sau khi kết xuất. Nhưng bên trong componentDidUpdate()bạn gọi lại setState() , điều này tạo ra một cuộc gọi tiếp theo đến cùng một vòng đời, và do đó vòng lặp cứ lặp đi lặp lại.

Nếu bạn phải sử dụng componentDidUpdate()và gọi setState()bên trong, quy tắc ngón tay cái, luôn đặt điều kiện dừng trước nó. Trong trường hợp của bạn, nó sẽ là:

componentDidUpdate () {
  if (this.state.data) {
    if (this.state.totalInspections !== this.state.data.length) {
      this.setState({ totalInspections: this.state.data.length })
    }
  }
}

0

Vì vậy, vấn đề của bạn là trạng thái isLoading cần phải được đặt SYNCHRONOUSLY trước bất kỳ cuộc gọi không đồng bộ nào.

Vì vậy, trong thành phầnDidMount của bạn:

componentDidMount() {
    try {
      this.setState({ loading: true }); // YOU NEED TO SET TRUE HERE
      this.fetchData();
    } catch (err) {
      console.log(err);
      this.setState({
        loading: false
      })
    }
}

Điều này đảm bảo tải ngay khi bạn thực hiện cuộc gọi. Sau đó, cuộc gọi của bạn được thực hiện và phần đó là ASYNCHRONOUS. Ngay sau khi dữ liệu đi qua tải xong

.then(data => {
  this.setState({
    data: data,
    loading: false, // THIS NEEDS TO BE FALSE
    totalInspections: this.state.data.length
  })
})

Hơn nữa: phương thức kết xuất của bạn có thể có nhiều câu lệnh trả về Thay vì có jsx có điều kiện, hãy trả về bố cục tải của bạn

render() {

    if (this.state.loading) {
        return <div> I am loading </div>
    }

    return <div> Proper Content </div>;

}

0

Đây là giải pháp của tôi.

class App extends Component {

    constructor(props) {
        super(props);
        this.state = {
            data: [],
            dateInput: '2019-10-01',
            loading: false,
            error: false
        };
    }

    async componentDidMount() {
        try {
            await this.fetchData(this.state.dateInput);
        } catch (err) {
            this.setState({ loading: false, error: true });
        }
    }

    fetchData = (date) => new Promise(resolve => {
        this.setState({ loading: true });
        fetch(`https://data.cityofnewyork.us/resource/p937-wjvj.json?$where=latitude > 39 AND latitude< 45 AND inspection_date >= '${date}'&$limit=50000`)
            .then(res => res.json())
            .then(res => {
                this.setState({ data: res, loading: false, error: false });
                resolve(res.data);
            });
    })

    handleDateInput = e => {
        this.setState({ dateInput: e.target.value }) //update state with the new date value
        this.fetchData(e.target.value);
    }

    render() {
        const { loading, data } = this.state;
        return (
            <div>
                {loading && (
                    <div className={classes.splash_screen}>
                        <div className={classes.loader}></div>
                    </div>
                )}
                {data && <StatCard totalInspections={data.length} />}
                <Dates handleDateInput={this.handleDateInput} />
                <Leaf data={data} />
            </div>
        );
    }
}

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.