我对问题的回答有效,回答中包含的Pedrag的评论也有效
我正在进行http请求调用,并且直到http响应返回之前都不想显示页面(请求调用为getRoadmaps)。我有一个称为“正在加载”的redux状态,以确定响应是否回来了?关于如何在我的代码中实现的任何见解?我的其他还原状态是路线图,其中包含一个也称为路线图的对象(对不起,抱歉)。
P.S。我看到了说做的一些答案(伪代码):如果未加载,则显示加载屏幕,否则加载渲染中的普通屏幕。但是我的问题并不存在于渲染中,而是存在于我做的
的componentWillMount()中。this.props.getRoadmaps()
,然后在3行之后我做
console.log(this.displayRoadmap[0].roadmap[0])
如果getRoadmaps()完成,应该成功记录路线图,似乎调用了getRoadmaps(),但随后程序继续运行而没有完全完成getRoadmaps(),这导致我的displayRoadmap无法定义。这还会导致一些奇怪的现象,例如,如果我从一个屏幕转到该组件,它将始终有效,但是如果刷新页面,它将无法正常工作
import React, { Component } from "react";
import Tree from "./Tree";
import TreeSidebar from "./TreeSidebar";
import { withRouter } from "react-router-dom";
import { connect } from "react-redux";
import { getRoadmaps } from "../actions/roadmapAction";
class OneRoadmap extends Component {
constructor(props) {
super(props);
this.state = {
loading: this.props.roadmap.loading,
roadmapName: "click a white circle to show more!",
roadmapImg:
"https://cdn3.iconfinder.com/data/icons/harmonicons-06/64/plus-circle-512.png",
roadmapDetail: [{ text: "Click on something" }, { text: "hi" }],
treeData: //deleted,just the default big json object
};
}
componentWillMount() {
this.props.getRoadmaps();
var location1 = this.props.location.pathname;
var n = location1.slice(9);
var current_roadmaps = this.props.roadmap.roadmaps;
this.displayRoadmap = current_roadmaps.filter(
eachRoadmap => eachRoadmap._id == n
);
// now we have a roadmap
console.log(this.displayRoadmap[0].roadmap[0]);
this.setState({ treeData: this.displayRoadmap[0].roadmap[0] });
console.log("is good");
console.log(this.props.loading);
}
componentDidMount() {}
handle_on_click_change = d => {
this.setState({ roadmapName: d.data.name });
this.setState({ roadmapImg: d.data.img });
if (d.data.details == undefined) {
this.setState({
roadmapDetail: [{ text: "The author did not put anything here" }]
});
} else {
this.setState({ roadmapDetail: d.data.details });
}
};
render() {
return (
<div>
{console.log(this.state.loading)}
<ul>
<li styles={{ float: "left" }}>
<div>
{console.log(this.state.treeData)}
<Tree
on_click_change={this.handle_on_click_change}
roadmapData={this.state.treeData}
/>
</div>
</li>
<li styles={{ float: "right" }}>
<div>
<TreeSidebar
displayName={this.state.roadmapName}
displayImg={this.state.roadmapImg}
displayDetail={this.state.roadmapDetail}
/>
</div>
</li>
</ul>
</div>
);
}
}
const mapStateToProps = state => ({
roadmap: state.roadmap
});
export default connect(
mapStateToProps,
{ getRoadmaps }
)(OneRoadmap);
答案 0 :(得分:2)
我个人如何使用css样式,我不知道这是否是最好的方法,但这对我有用,我会做类似的事情
this state = {
loaderStyle: 'block',
contentStyle: 'none'
}
componentDidMount() {
If(this.displayRoadmap[0].length > 0) {
this.setsState({loaderStyle: 'none', contentStyle:
'block:
} else /// do something
};
在渲染功能中,我将执行此操作
<Loader style={{display: this.state.loaderStyle}}/>
<Content style={{display: this.state.contentStyle}}>.
</Content>
答案 1 :(得分:0)
首先也是最重要的一点,不要使用componentWillMount
,而要使用componentDidMount
。 UNSAFE_componentWillMount()
是旧版本,将在版本17中删除。现在,进入下一期,您希望通过将loading
状态设置为true来开始页面。
this.state = {
loading: true,
roadmapName: "click a white circle to show more!",
roadmapImg:
"https://cdn3.iconfinder.com/data/icons/harmonicons-06/64/plus-circle-512.png",
roadmapDetail: [{ text: "Click on something" }, { text: "hi" }],
treeData: //deleted,just the default big json object
};
在那之后,您需要稍微调整渲染方法以支持条件渲染:
render() {
if (this.state.loading) {
return <LoadingBar />;
}
return (
<div>
<ul>
<li styles={{ float: 'left' }}>
<div>
{console.log(this.state.treeData)}
<Tree
on_click_change={this.handle_on_click_change}
roadmapData={this.state.treeData}
/>
</div>
</li>
<li styles={{ float: 'right' }}>
<div>
<TreeSidebar
displayName={this.state.roadmapName}
displayImg={this.state.roadmapImg}
displayDetail={this.state.roadmapDetail}
/>
</div>
</li>
</ul>
</div>
);
}
现在,只要数据准备就绪,您就可以简单地执行this.setState({ loading: false })
,并且render方法将返回加载栏以外的任何内容。因此,在您的特定情况下:
this.setState({ treeData: this.displayRoadmap[0].roadmap[0], loading: false });
答案 2 :(得分:0)
这可以通过React高阶组件轻松实现,如下所示。
withLoadingScreen.js
import * as React from "react";
const withLoadingScreen = WrappedComponent => {
return class LoadingScreen extends React.Component {
render() {
if (this.props.loading) return <div className="pre-loader" > Loading... </div>
return <WrappedComponent {...this.props} />;
}
};
};
export default withLoadingScreen;
对组件使用HOC,如下所述
export default compose(
connect(mapStateToProps, mapActionCreators),
withLoadingScreen
)(OneRoadmap)
您也可以将自定义参数传递给HOC。 有关更多示例,请点击下面的链接。通过引用对代码进行所需的更改。
https://medium.com/@Farzad_YZ/handle-loadings-in-react-by-using-higher-order-components-2ee8de9c3deb
答案 3 :(得分:0)
我检查了elraphty的答案,因为他确实回答了我的部分问题,他也希望我检查他的答案。无论如何,如果您在获取数据并等待数据完成获取时遇到麻烦,这是我如何做的一个完整示例。 Predrag Beocanin的评论有效:
fetch('some_url', { method: 'GET' }).then(res = res.json()).then(data => { // some parse here; return parsed}
这是我的操作方法(使用axios代替metch,将请求发送到另一个完全不同的文件/ api / roadmap,然后使用Redux更新商店。
在OneRoadmap.js中,这是我需要提取数据的组件,这就是我所谓的提取数据:
async componentDidMount() {
await this.props.getRoadmaps();
.....
}
这使得我们可以运行this.props.getRoadmaps()并等到该行完成后再转到下一行。如果您不进行异步/等待,则this.props.getRoadmaps()将触发,但是componentDidMount()中的代码将立即继续运行,而无需this.props.getRoadmaps()完成数据获取,然后更新状态。 现在,当然,Predrag的答案肯定可以解决此问题,但是如果您希望将数据获取和使用redux进行状态更新的文件放在不同的文件中(像我一样),请继续阅读。
这是getRoadmaps()的工作,它位于名为RoadmapActions.js的文件中:
export const getRoadmaps = () => dispatch => {
dispatch(setRoadmapsLoading());
return axios
.get("/api/roadmaps")
.then(res => dispatch({ type: GET_ROADMAPS, payload: res.data }));
};
这表示我们将发送一个get请求到“ / api / roadmaps”,然后从get请求中获取返回数据,然后将一个调度发送到redux商店,这将更新商店状态,并且我们最终在OneRoadmap.js中使用它。这是/ api / roadmaps获取请求返回的内容:
router.get("/", (req, res) => {
Roadmap.find()
.sort({ date: -1 })
.then(roadmaps => res.json(roadmaps));
});
Roadmap.find()进入我们的mongo数据库并检索所有路线图项目,然后将其返回到调用它的任何地方。
使用返回的数据,我们将带有该数据的分派发送到减速器,这就是GET_ROADMAPS()所做的事情,GET_ROADMAPS位于roadmapReducer.js中:
const initialState = {
roadmaps: [],
loading: false,
current_roadmap: ""
};
export default function(state = initialState, action) {
switch (action.type) {
case GET_ROADMAPS:
return {
...state,
roadmaps: action.payload,
loading: false
};
}
然后就是这样,您的redux存储状态已更新,并且由于我将OneRoadmap.js与state.roadmap连接起来,因此可以在代码中自由使用它。