Re-rendering 一个 ReactJS 组件挂起浏览器
Re-rendering a ReactJS component hangs browser
我一直在尝试使用 ReactJS 创建一个基于 UI 的组件,而不是我通常使用一百万个全局函数、变量和 non-reusable 标记的草率方法。到目前为止,我真的很喜欢 React,但我遇到了一个绊脚石。
考虑以下组件布局
EventView
EventViewSidebar
EventViewList
EventViewListRow
EventViewDetail
在此布局中,每个唯一键都出现多次 EventViewListRow
。单击 EventViewListRow
的实例应使用该项目的详细信息更新 EventViewDetail
。
这是顶级 EventView
组件的 render
函数:
render: function () {
return (
<div className="event-view row-fluid">
<div className="event-view__sidebar col-md-4">
<EventViewSidebar projectId={this.state.projectId} />
</div>
<div className="event-view__content col-md-8" id="eventDetail">
</div>
</div>
);
}
这是 EventViewDetail
组件
var EventViewDetail = React.createClass({
getInitialState: function () {
return { eventId: 0 };
},
render: function () {
if (this.state.eventId === 0) {
return (<h3>Nothing selected</h3>);
}
else {
return (
<div>
{this.state.eventId}
</div>
);
}
}
});
为了在单击 EventViewListRow
时更新 EventViewDetail
,我在 EventViewListRow
中定义了以下事件处理程序
handleClick: function (event) {
event.preventDefault();
React.render(
React.createElement(EventViewDetail, { eventId: this.props.id }),
document.getElementById("eventDetail")
).setState({ eventId: this.props.id });
},
这一切似乎都运行良好(除了我必须在上面添加的 setState
调用之外,否则单击不同的 EventViewListRow
似乎没有任何效果 - 毫无疑问这是我的第一个问题)。实际的关键问题是,如果我将默认 html 添加到 EventView
中定义的 eventDetail
div,那么当我单击 EventViewListRow
中的 link 时, 控制台中显示以下消息,浏览器挂起。
Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:
(client) <h3 data-reactid=".0">Nothing selected
(server) <h3 data-reactid=".0.1.0">Select an even
浏览器选项卡 (Chrome 43) 挂起后,我必须使用任务管理器将其终止。
本来我是直接调用EventViewDetail
的一个实例,比如
<div className="event-view__content col-md-8" id="eventDetail">
<EventViewDetail />
</div>
但如果我只使用香草,它也会挂起 HTML
<div className="event-view__content col-md-8" id="eventDetail">
<h3>Select an event to view</h3>
</div>
显然我做错了什么,但我对 React 有点陌生,所以我不知道那是什么。我读到我应该在顶级 EventView
组件上有状态,但我无权访问它并且 React 似乎不提供返回组件链的能力。除非你应该将 EventView
实例作为 属性 传递给每个 child 组件?
哦,我还应该补充 - 我还尝试从 EventViewListRow
单击处理程序中删除 setState
调用,以防万一这是原因,但没有效果。
任何人都可以就我做错了什么提供任何建议。 EventView
是否应该具有 child 组件的所有状态,如果是这样,我如何从嵌套的 child 组件引用 parent - 我是否必须传递实例EventView
作为每一个 child?
的支柱
抱歉,如果这些是白痴问题!
您不应在 handleClick 函数中调用 React.render。只需调用 this.setState,React 将自动再次渲染。
我一直在尝试使用 ReactJS 创建一个基于 UI 的组件,而不是我通常使用一百万个全局函数、变量和 non-reusable 标记的草率方法。到目前为止,我真的很喜欢 React,但我遇到了一个绊脚石。
考虑以下组件布局
EventView
EventViewSidebar
EventViewList
EventViewListRow
EventViewDetail
在此布局中,每个唯一键都出现多次 EventViewListRow
。单击 EventViewListRow
的实例应使用该项目的详细信息更新 EventViewDetail
。
这是顶级 EventView
组件的 render
函数:
render: function () {
return (
<div className="event-view row-fluid">
<div className="event-view__sidebar col-md-4">
<EventViewSidebar projectId={this.state.projectId} />
</div>
<div className="event-view__content col-md-8" id="eventDetail">
</div>
</div>
);
}
这是 EventViewDetail
组件
var EventViewDetail = React.createClass({
getInitialState: function () {
return { eventId: 0 };
},
render: function () {
if (this.state.eventId === 0) {
return (<h3>Nothing selected</h3>);
}
else {
return (
<div>
{this.state.eventId}
</div>
);
}
}
});
为了在单击 EventViewListRow
时更新 EventViewDetail
,我在 EventViewListRow
handleClick: function (event) {
event.preventDefault();
React.render(
React.createElement(EventViewDetail, { eventId: this.props.id }),
document.getElementById("eventDetail")
).setState({ eventId: this.props.id });
},
这一切似乎都运行良好(除了我必须在上面添加的 setState
调用之外,否则单击不同的 EventViewListRow
似乎没有任何效果 - 毫无疑问这是我的第一个问题)。实际的关键问题是,如果我将默认 html 添加到 EventView
中定义的 eventDetail
div,那么当我单击 EventViewListRow
中的 link 时, 控制台中显示以下消息,浏览器挂起。
Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:
(client) <h3 data-reactid=".0">Nothing selected
(server) <h3 data-reactid=".0.1.0">Select an even
浏览器选项卡 (Chrome 43) 挂起后,我必须使用任务管理器将其终止。
本来我是直接调用EventViewDetail
的一个实例,比如
<div className="event-view__content col-md-8" id="eventDetail">
<EventViewDetail />
</div>
但如果我只使用香草,它也会挂起 HTML
<div className="event-view__content col-md-8" id="eventDetail">
<h3>Select an event to view</h3>
</div>
显然我做错了什么,但我对 React 有点陌生,所以我不知道那是什么。我读到我应该在顶级 EventView
组件上有状态,但我无权访问它并且 React 似乎不提供返回组件链的能力。除非你应该将 EventView
实例作为 属性 传递给每个 child 组件?
哦,我还应该补充 - 我还尝试从 EventViewListRow
单击处理程序中删除 setState
调用,以防万一这是原因,但没有效果。
任何人都可以就我做错了什么提供任何建议。 EventView
是否应该具有 child 组件的所有状态,如果是这样,我如何从嵌套的 child 组件引用 parent - 我是否必须传递实例EventView
作为每一个 child?
抱歉,如果这些是白痴问题!
您不应在 handleClick 函数中调用 React.render。只需调用 this.setState,React 将自动再次渲染。