Papa.parse componentDidMount shouldComponentUpdate 混乱

Papa.parse componentDidMount shouldComponentUpdate confusion

编辑:我认为这是 codesandbox 的 CORS 问题,但我还没有弄清楚如何使用静态 ip 甚至 localhost 进行托管。当我确认这是 papaparse 和 codesandbox 云之间的 CORS 问题时,我会更新 ide。我针对与 Domino 在同一个 papaparse 应用程序

上解决的问题不同的问题启动了 new question

Whosebug 上的这个问题是我与 Papa.parse 对话的延伸。

找到一个模式 here,类似地,我使用 this.function 传递每个对象,因为它是用 "City" 参数解析的,并尝试呈现 "WeatherCitySkyMap"每个城市的组成部分。如果我硬编码 let cities = [{ city: "New York" }, { city: "Baltimore" }];,渲染后的代码已经过测试,可以为 cities 数组中的每个城市渲染这样的组件;但是对于从北美 csv 城市列表的保管箱 link 解析的每个城市,我希望按 Papa.parse 步骤填充城市。

class CitiesMap extends React.Component {
  constructor(props) {
    super(props);
    this.updateData = this.updateData.bind(this);
  }
  componentDidMount() {
    Papa.parse(
      "https://cors-anywhere.herokuapp.com/https://www.dropbox.com/s/5vcoo9r60hgczd1/worldcitiespop_northamerica_nolonglat.csv?dl=1",
      {
        download: true,
        header: true,
        worker: true,
        skipEmptyLines: true,
        step: this.updateData,
        complete: function() {
          console.log("all done");
        }
      }
    );
  }
  updateData(results) {
    cities.push(results.data, ["City"]);
    this.setState({ cities });
  }
  render(props) { 
    let filteredCities = cities.filter(cities => {
      return (
        cities.City.toUpperCase().indexOf(this.props.search.toUpperCase()) !==
        -1
      );
    });
    return (
      <div>
        <div className="Cities">
          {filteredCities.map(City => {
            return (
              <div>
                <WeatherCitySkyMap
                  description={this.description}
                  humidity={this.humidity}
                />
                {JSON.stringify([City])
                  .replace(/[^\w\s]/g, "")
                  .replace(/(city)/g, "")}
              </div>
            );
          })}
        </div>
      </div>
    );
  }
}

export default CitiesMap;

"This pattern is found here" link 使用 UNSAFE_componentWillMount()),而不是我尝试在 Papa.parse 周围使用 componentDidMount(),但需要 Papa.parse results.data 在它们像 componentWillMount() 那样渲染之前发生(或者我应该在某个地方使用 shouldComponentUpdate & forceUpdate() 吗?)。我读到的最佳做法是用构造函数和 super 替换 componentWillMount,所以我应该把 Papa.Parse 放在构造函数中吗?我试过了,但迷路了。感谢您提前阅读和帮助。

Domino987 回答后的更新(到目前为止):

import React from "react";
import WeatherCitySkyMap from "./WeatherCitySkyMap";
import Papa from "papaparse";

import ".././Explore/Cities.css";

class CitiesMap extends React.Component {
  constructor(props) {
    super(props);
    this.updateData = this.updateData.bind(this);
    this.state = { cities: [] };
  }
  componentDidMount() {
    Papa.parse( "https://dl.dropboxusercontent.com/s/k81s5enbamijuke/worldcitiespop_northamerica_nolonglat_few.csv?dl=0",
      {
        download: true,
        header: true,
        worker: true,
        skipEmptyLines: true,
        step: this.updateData,
        complete: function() {
          console.log("all done");
        }
      }
    );
  }
  updateData(results) {
    this.setState(prevState => ({
      cities: [...prevState.cities, results.data.City]
    }));
  }
  render(props) {
    let filteredCities = this.state.cities.filter(cities => {
      return (
        cities.toUpperCase().indexOf(this.props.search.toUpperCase()) !==
        -1
      );
    });
    return (
      <div>
        <div className="Cities">
          {filteredCities.map(City => {
            return (
              <div>
                <WeatherCitySkyMap
                  description={this.description}
                  humidity={this.humidity}
                />
                {JSON.stringify([City])
                  .replace(/[^\w\s]/g, "")
                  .replace(/(city)/g, "")}
              </div>
            );
          })}
        </div>
      </div>
    );
  }
}

export default CitiesMap;

所以对于组件的工作原理存在一些误解:

  1. 道​​具未传递给渲染:您可以使用 this.props.
  2. 访问它们
  3. 开始时本地状态为 null:在您的构造函数中写入 this.state = {cities: []},如果您尝试在渲染中访问城市,这将防止破坏您的代码。
  4. 要在渲染和更新数据中访问城市,请使用 this.state.cities。这样您就可以访问当前的城市。
  5. 要更新状态中的数组,请这样写:this.setState(prevState => { cities: [...prevState.cities, results.data.City] });。这将更新不可变的状态并保留以前的城市。

componentDidMount 是实现服务器调用、副作用或 Papa.parse 的正确方法。它会首先渲染没有数据的组件,但一旦数据出现,它就会更新它。该组件不会中断,因为对于第 2 点,状态不会为 null 并且渲染仍然有效。

我希望这些评论能帮助您使代码正常工作。

// 编辑 既然你问如何实现 updateData 和渲染,这里是一些代码:

updateData(results) {
  // This will not work because cities is not defined here (us this.state.cities) and you mutate the data with push
  // cities.push(results.data.city); 
  // I am not sure why you add "City" but that is in your code
  this.setState(prevState => { cities: [...prevState.cities, results.data.City]});
}
render(props) {
  // Filter will check each city in the cities array, so you have to write it like this:
  const filteredCities = this.state.cities.filter(city => city.indexOf(this.props.search.toUpperCase()) !== -1);
}

编码愉快。