我在阻止 div flash 时遇到了一些麻烦,其中 react 将呈现错误消息然后接收 Prop 并最终呈现 Prop 。
在我的EventsView
组件我有以下。
view.js
var view;
if (_.size(this.props.events) !== 0) {
view = this.props.events.map(function(year) {
return <YearView year={year} />;
});
} else {
view = <NoEventsView />
}
所以变量 view
被渲染,最初没有this.props.events
在页面加载时,因为我有文件的另一部分创建它。创建 this.props.events 的那一刻,事件就会被渲染。这是通过 react.Backbone
完成的。混音。
我尝试过使用一些组件生命周期方法,例如 componentWillUpdate
.问题是他们似乎不想按照我希望他们工作的方式工作,并且永远不会呈现错误消息。下面是我尝试过的(以及其他)示例
我想过做这样的事情。
view.js
componentWillUpdate: function(nextprops, nextstate) {
if (_.size(nextprops.events) !== 0) {
var view = nextprops.events.map(function(year) {
return <YearView year={year} />;
});
this.setState({
view: view
});
} else {
this.setState({
view: <NoEventsView />
})
}
},
// render this.state.view
然后我将设置 getInitialState:view
到一个 this.props.events
map 。
*EDIT - 一个临时且糟糕的解决方法 *
所以我遇到的问题是我有一个顶级组件接受一个像这样的全局变量的 Prop
view.js
React.render(<EventsView events={theseEvents} />, document.getElementById('mainContent'));
theseEvents
实际上是在另一个文件中初始化的 Backbone Collection 全局变量。
加载文档时 theseEvents
将无人居住,因此我的 View 将闪烁 <NoEventView />
然后在 theseEvents
时重新渲染然后填充。这是由下图所示的主干混合处理的。
Dan 的解决方案为我指明了正确的方向。我设置了一个全局变量 window.hasEvents
根据我从我的 ajax 请求返回的内容设置为 true 或 false,但到那时 React 已经在渲染(组件将以 hasEvents
开始为 true,到它完成时 hasEvents
可能为 false)。即使我做了hasEvents
<EventsView />
的 Prop 当它改变时,react 不会重新渲染。
因此,作为临时解决方法,我默认了 hasEvents
真实和渲染EventsView
.然后我等待组件加载并检查它是否与 hasEvents 同步。如下图所示。老实说,这种解决方法不是很愉快。
view.js
ar EventsView = React.createBackboneClass({
mixins: [
React.BackboneMixin("events", "all")
],
getInitialState: function() {
return {
hasEvents: window.hasEvents
}
},
componentDidMount: function() {
var model = this;
// This waits after component loading to check whether hasEvents is the same
setTimeout(function() {
if(!(model.state.hasEvents == window.hasEvents)) {
model.setState({
hasEvents: window.hasEvents
})
};
}, 1000);
},
render: function() {
var view;
if (this.props.events.length > 0) {
view = this.props.events.map(function(year) {
return <YearView year={year} />;
});
}
if (!this.state.hasEvents) {
view = <NoEventsView />
}
return {
// other parts of the page were also rendered here
{view}
}
});
基本上是 componentDidMount
组件安装后等待一段时间,然后仔细检查全局变量。绝对不是一个很好的解决方法,尤其是因为它依赖于 1 秒 theseEvents
人口,它只适用于初始组件安装。
最佳答案
您的第二种方法不是“React 方式”(尽管从技术上讲它可能有效),因为您不应该将 React 元素置于状态。只有数据应该去那里,并且在 render
中如果需要弄清楚该数据如何对应于 DOM 结构。除非绝对必要,否则最好避免使用 state
。
话虽如此,我不太确定您要实现什么目标。假设您想在事件发生之前防止“无事件”闪烁,您的组件可以做到这一点的唯一方法是知道正在获取数据。如果除了 events
属性之外,你还传递了 isLoading
bool 属性,你可以这样做:
render: function () {
var isEmpty = this.props.events.length === 0;
if (isEmpty) {
return this.props.isLoading ?
<p>Loading...</p> : // note you can also return null here to render nothing
<NoEventsView />;
}
return this.props.events.map(function (year) {
return <YearView year={year} />;
});
}
关于javascript - 在决定渲染之前 react 等待 map 功能以防止div闪烁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27841270/