更新 => 试试这个,看看你是否可以从子组件记录道具:
import React from "react";
import MovementDataDisplay from "./MovementDataDisplay";
import OverviewDataDisplay from "./OverviewDataDisplay";
import DistributionDataDisplay from "./DistributionDataDisplay";
class DataDisplay extends React.Component {
constructor(props) {
super(props);
}
render() {
const { passAPIData } = this.props
const {siteHours, movingHours} = passAPIData
console.log(siteHours, movingHours)
if (this.props.NavState === "movement") {
return (
<div className="chart-container">
<MovementDataDisplay
Data={passAPIData}
Title="Site Hours"
Labels={['inside','outside']}
/>
<MovementDataDisplay
Data={[1,3]}
Title="Moving Hours"
/>
</div>
);
} else if (this.props.NavState === "overview") {
return (
<div className="chart-container">
<OverviewDataDisplay
Data={[3.3176110809420893, 4.18238891905791]}
Title="Site Hours"
/>
<OverviewDataDisplay
Data={[3.9176110809420893, 4.18238891905791]}
Title="Moving Hours"
/>
</div>
);
} else if (this.props.NavState === "distribution") {
return <DistributionDataDisplay />;
}
}
}
export default DataDisplay;
没有拉出 repo 并调试它,或者运行它(诚然)我的猜测是,当您在子组件的 componentDidMount 中设置状态并丢失该值时,您会导致重新渲染(只是猜测) - 在这里我已经一起删除了state(我看不出它是如何需要的)和componentDidMount,并直接从道具中记录你正在寻找的值。如果这些值是在父状态中设置并作为道具传递的,那么我没有任何理由可以看到(从您目前拥有的)您需要重新设置它们以再次在子状态中声明。到目前为止,除了为它设置道具之外,您甚至似乎没有在子组件中使用任何状态,除非这些值将在此子组件中本地更改……您可以(并且应该)只阅读它们来自定义、更新和传递它们 的父级的 props。
更新再次(在修改了实际代码之后;))
检查一下,看看它是否能解决您的问题。我为我所做的小改动添加了 cmets:
App.js:
import React from "react";
import Nav from "./components/Nav";
import DataDisplay from "./components/DataDisplay";
import "./styles/App.css";
import fastapi from './api/fastapi'
class App extends React.Component {
constructor() {
super();
this.state = {
userDate: "",
apiData: {}, // this was set to a [] but it's data type is a actually an {}
navState: "overview"
};
this.setNavState = this.setNavState.bind(this);
}
setNavState(nav) {
// when triggering this from the UI it causes a state change, and a re-render
const btnArr = ["overview", "movement", "distribution"];
this.setState({ navState: btnArr[nav] });
// this needs to be reset
this.onDateChange(this.state.userDate)
}
onDateChange = async date => {
const response = await fastapi.get(`/${date}`)
console.log('onDateChange response.data', response.data)
this.setState({
apiData: response.data,
userDate: date ? date : this.state.userDate // you were not setting this but you will need it for when setNavState runs
})
}
render() {
console.log("new state is ",this.state.apiData) // you should see this
return (
<div className="App">
<Nav getNav={this.setNavState} getDate={this.onDateChange} />
<DataDisplay NavState={this.state.navState} apiData={this.state.apiData}/>
</div>
);
}
}
export default App;
日期显示.js
import React from "react";
import MovementDataDisplay from "./MovementDataDisplay";
import OverviewDataDisplay from "./OverviewDataDisplay";
import DistributionDataDisplay from "./DistributionDataDisplay";
class DataDisplay extends React.Component {
constructor(props) {
super(props);
}
render() {
console.log("from DataDisplay: ", this.props.apiData)
const { apiData : { site_hours = {} }} = this.props
const {inside = 0, outside = 0} = site_hours // defaults to avoid breaking if there is no data here (prior to selecting date for ex)
console.log(inside, outside) // i can see these logs in the child :)
if (this.props.NavState === "movement") {
return (
<div className="chart-container">
<MovementDataDisplay
Data={[inside, outside]} // you are putting the entire 'this.state' here (a big object), but it seems to want a simple array
Title="Site Hours"
Labels={['inside','outside']}
/>
<MovementDataDisplay
Data={[1,3]}
Title="Moving Hours"
/>
</div>
);
} else if (this.props.NavState === "overview") {
return (
<div className="chart-container">
<OverviewDataDisplay
Data={[3.3176110809420893, 4.18238891905791]}
Title="Site Hours"
/>
<OverviewDataDisplay
Data={[3.9176110809420893, 4.18238891905791]}
Title="Moving Hours"
/>
</div>
);
} else if (this.props.NavState === "distribution") {
return <DistributionDataDisplay />; // you need to pass this some data of course :)
}
}
}
export default DataDisplay;
我可以看到孩子的日志,不需要状态。 我看到和 IDK 的问题,如果这就是您所说的,是在概览/运动/分布图表之间单击时分页。这是因为您的 api 响应存储到父组件中的本地状态,当您通过在导航中调用 setNavState 更新状态时,您会在该父组件中触发重新渲染并且状态丢失,您需要重新获取数据 - 分页是因为数据不再可供该孩子使用,并且没有适当的保护措施来处理没有数据(这是您应该始终为记录编码的内容)所以我
1) 保存状态中的日期
2)并在同一个导航回调中重新获取它(这可能有效,因为 setState 是异步的)
3) 为孩子添加了一些默认值以防止破坏
如果此应用具有全局状态,您可以将 apiResponse 存储在那里而无需重新获取,或者您可以将其存储在本地存储甚至 cookie 中以避免重新获取。全局状态更可取。