I've read many posts but this is my first question! Let me first thank everyone for their support, and offer a description of the problem before a lengthy block of code! Any help is appreciated...I think I'm close!
QUESTION/PROBLEM: my setState method only works on the initial data fetch. Subsequent attempts will fetch the new data, but don't reset the state, and therefore the child component does not receive new props!
WHY/WHAT: I'm using papa parse to fetch csv data and convert it to JSON, and then pass this data to the child. I am using a D3 map library called react-simple-maps, and then calling animations with GSAP/Greensock.
Papa parse defaults to a callback instead of a promise (although promises are possible), so I've created an _.isMounted method that I can toggle...reason for this was that once I fetched data async, my animations would no longer run in the child/map component as they are called in componentDidMount before the fetch was complete! now my fix is working, but won't work over and over again! I will be passing new data to create sets of map markers several times and hour! See my commented code below!
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;