我一直在挠头试图弄清楚这一点,尝试了所有我能想到的/在网上找到的东西,但没有运气。 当组件安装时,我从 API 中检索一个列表,解析它并将其推送到我所在状态的另一个数组中。我已经检查了 api 并且它工作正常,我得到了数据,在调试时我看到逻辑运行正常,我的控制台日志按预期触发。我看到的唯一问题是渲染。
我正在 ComponentDidMount 中执行以下调用:
ScheduleService.getScheduleList().then((response) =>
response.data.scheduleList.forEach((schedule: any, index: any) =>
this.state.nodes?.push({
id: index,
label: (
<div onClick={(e) => this.handleScheduleClick(e)}>
<Tooltip2
content={
"Start: " +
schedule.startTime.utc +
" Stop: " +
schedule.stopTime.utc +
" Type: " +
schedule.scheduleType
}
placement="right"
>
{schedule.id}
</Tooltip2>
</div>
),
isExpanded: false,
icon: "document",
})
)
);
我试过在回调中添加这个调用.. 不走运。尝试将值分配给数组并随后更新状态,结果相同。
当我第一次点击路由器并进入页面时,我的树没有被填充。 Data not rendered
但在我立即切换回此页面后,我的数据呈现出来。
我知道每次状态改变时 React 都会更新组件,但我不明白为什么现在没有发生。
也试过运行 this.forceUpdate(),结果一样。
非常感谢您的帮助!
编辑 1: 我已经写在我正在使用的逻辑下面。
public state: IState= {
nodes: ITreeNode[],
}
class MyClass extends React.Component<IState> {
public componentDidMount(){
this.getScheduleList();
}
private getScheduleList = () => {
ScheduleService.getScheduleList().then((response) =>
response.data.scheduleList.forEach((schedule: any, index: any) =>
this.state.nodes?.push({
id: index,
label: (
<div onClick={(e) => this.handleScheduleClick(e)}>
<Tooltip2
content={
"Start: " +
schedule.startTime.utc +
" Stop: " +
schedule.stopTime.utc +
" Type: " +
schedule.scheduleType
}
placement="right"
>
{schedule.id}
</Tooltip2>
</div>
),
isExpanded: false,
icon: "document",
})
)
);
public render() {
return (
<div>
<Tree
contents={this.state.nodes}
className={
" focus-panelsList focus-panelsList-noborder"
}
/>
</div>
}
)
答案 0 :(得分:2)
首先,您不能直接编辑状态。为了更新状态和反应识别状态的变化是通过使用 this.setState
方法。
其次,您不应该在状态中存储组件。您可以在组件的 state 和 render 方法中存储所需的数据,使用 map 函数通过 nodes
并生成标签组件。
我重构了 getScheduleList
方法。 '我已经更新了它,因此它将节点设置为这个数组,而不是在每次迭代时更新状态。
private getScheduleList = () => {
ScheduleService.getScheduleList().then((response) => {
const nodesData = response.data.scheduleList.map((schedule: any, index: any) => ({
id: index,
schedule: schedule,
label: {
content: "Start: " +
schedule.startTime.utc +
" Stop: " +
schedule.stopTime.utc +
" Type: " +
schedule.scheduleType,
id: schedule.id,
},
isExpanded: false,
icon: "document",
}));
this.setState({nodes: nodesData})
});
}
然后你可以在你的渲染方法中生成标签组件
public renderLabels() {
return (
<div>
{this.state.nodes.map(n => {
return (
<div key={"node-label-" + n.id} onClick={(e) => this.handleScheduleClick(e)}>
<Tooltip2
content={n.label.content}
placement="right"
>
{n.label.id}
</Tooltip2>
</div>
);
})}
</div>
);
}
public render() {
return this.renderLabels());
}
或者因为您需要在 Tree 组件的节点数组中自定义标签组件,您可以执行类似的操作。
public renderNodeLabel(node) {
return (
<div key={"node-label-"+node.id} onClick={(e) => this.handleScheduleClick(e)}>
<Tooltip2
content={node.label.content}
placement="right"
>
{node.label.id}
</Tooltip2>
</div>
);
}
public render() {
return (
<Tree
contents={this.state.nodes.map(n => ({
...n,
label: this.renderNodeLabel(n),
}))}
className="focus-panelsList focus-panelsList-noborder"
/>
)
}
答案 1 :(得分:1)
看来您的问题是状态突变。如果您正在加载数据并填充 ScheduleService.getScheduleList()
.then((response) => {
this.setState((prevState: IState) => ({
nodes: prevState.nodes.concat(response.data),
}));
});
状态数组,则不应推送到当前状态。
使用功能状态更新从任何先前存在的状态进行更新,并附加新映射的空对象数组。
其次,您将 JSX 存储在 React 反模式的 state 中。您应该只存储数据,然后将状态映射到您需要传递给第三方模块的 JSX。
const data = this.state.nodes.map((schedule: any, index: any) => ({
id: index,
label: (
<div onClick={this.handleScheduleClick}>
<Tooltip2
content={
"Start: " +
schedule.startTime.utc +
" Stop: " +
schedule.stopTime.utc +
" Type: " +
schedule.scheduleType
}
placement="right"
>
{schedule.id}
</Tooltip2>
</div>
),
isExpanded: false,
icon: "document",
}));
将状态映射到 JSX
data
将 this.state.nodes
传递给第三方组件,而不是您之前可能执行的 class MyClass extends React.Component<IState> {
state = {
nodes: [],
};
public componentDidMount(){
this.getScheduleList();
}
。
除此之外,您也没有初始状态。您应该提供有效的初始状态。
readJson()