簡體   English   中英

不能觸發setState並對后續數據獲取(帶有papa解析)做出反應,以傳遞新的道具來重新呈現子組件嗎?

[英]Can't trigger setState with react on subsequent data fetch w/ papa parse to pass new props to rerender child component?

我讀了很多帖子,但這是我的第一個問題! 首先,讓我感謝所有人的支持,並在冗長的代碼塊之前提供對問題的描述! 任何幫助表示贊賞...我想我已經接近了!

問題/問題:我的setState方法僅適用於初始數據提取。 隨后的嘗試將獲取新數據,但不會重置狀態,因此子組件不會收到新的道具!

原因/原因:我正在使用papa解析來獲取csv數據並將其轉換為JSON,然后將此數據傳遞給子級。 我正在使用一個稱為react-simple-maps的D3地圖庫,然后使用GSAP / Greensock調用動畫。

爸爸解析默認為回調而不是承諾(盡管可能實現承諾),所以我創建了一個_.isMounted方法,可以切換...原因是因為一旦我異步獲取數據,我的動畫就不再在提取完成之前,在child / map組件中運行它們,就像在componentDidMount中調用它們一樣! 現在,我的修復程序正在運行,但不會一遍又一遍地工作! 我將在幾個小時內傳遞新數據來創建地圖標記集! 請在下面查看我的評論代碼!

 class MapContainerParent extends Component { _isMounted = false; //toggling this allows the child component to wait for data fetch to complete before render _isRefreshed = false; //tried, but not working? constructor(props) { super(props); this.state = { data: [], isLoading: true, error: null }; this.updateData = this.updateData.bind(this); } //I'm using papaparse to fetch and convert the csv file to JSON //it uses a callback instead of a promise, which may be the issue? fetchAndConvert() { //Papa Parse to convert CSV to JSON...also fetches from S3 bucket const Papa = require("papaparse"); const dataFilePath = "url of where the csv file lives"; Papa.parse(dataFilePath, { download: true, header: false, skipEmptyLines: true, complete: this.updateData //callback, which sets the state after the data is in proper format }); } //HEre is the callback updateData(result) { const data = result.data; const mapData = data.map(item => {..... //takes the resulting json and formats it console.log("MapData restructured:", mapData); if (this._isMounted) { //I THINK THE PROBLEM IS HERE! this.setState({ //Only sets the state on initial render! //makes sense since I have told it to setState when isMounted is true. //Since I'm fetching new data several times an hour, this won't do! //How can I add another condition to reset state when new data is present? data: mapData, isLoading: false, error: false }); } //tried to add an _isRefreshed condition, not working? else if (this._isMounted && this._isRefreshed === false) { this.setState({ data: mapData, isLoading: false, error: false }); } } componentDidMount() { this._isMounted = true; this.fetchAndConvert(); this._isRefreshed = true; //dn work setInterval(this.fetchAndConvert, 30000); //runs the function at an interval I set //I see the new data when I preview the network request //but it does not trigger a new setState??? } componentWillUnmount() { this._isMounted = false; this._isRefreshed = false; //not working... } renderLoading() { return <div > loading... < /div>; } renderError() { return <div > Error... < /div>; } renderMap() { return ( <div> <MapChild data = {this.state.data/> < </div> ); } render() { if (this.state.loading) { return this.renderLoading(); } else if (this.state.data.length > 0) { return this.renderMap(); } else { return this.renderError(); } } } export default MapContainerParent; 

調用間隔函數時, this不會是您期望的。

嘗試結合fetchAndConvertthis在構造像你這樣做updateData如預期它會奏效。

constructor(props) {
  super(props);
  this.state = {
    data: [],
    isLoading: true,
    error: null
  };
  this.updateData = this.updateData.bind(this);
  this.fetchAndConvert = this.fetchAndConvert.bind(this);
}

所以...使用_.isMounted調用setState存在問題。 根據React的這篇博客文章,它是反模式的:

https://reactjs.org/blog/2015/12/16/ismount-antipattern.html

盡管我在以下博客文章中使用了此方法,但在評論中對此問題進行了很好的持續對話,但我仍然沒有找到我認為的長期解決方案。 https://www.robinwieruch.de/react-warning-cant-call-setstate-on-an-unmount-component/

目前有效的方法是在子組件內部...在componentDidMount中調用動畫,並使用componentDidUpdate對數據/道具進行深度比較(我使用了lodash _.isEqual),如果它獲取了新數據,請殺死先前的動畫並再次加載。 在運行時,加載2秒鍾的動畫會花費一些時間來輸入數據。我不想共享此代碼,因為我也將其稱為“反模式”或只是一種不好的做法...但是它可以工作100%的時間! 當我找到更好的方法時,我會更新線程!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM