我有一个应用程序,我需要动态设置元素的高度(让我们说“app-content”) . 它采用应用程序的“chrome”的高度并减去它,然后将“app-content”的高度设置为在这些约束内适合100% . 使用vanilla JS,jQuery或Backbone视图这是非常简单的,但我很难弄清楚在React中执行此操作的正确流程是什么?
下面是一个示例组件 . 我希望能够将 app-content
的高度设置为窗口的100%减去 ActionBar
和 BalanceBar
的大小,但是如何知道何时渲染所有内容以及将计算内容放在此React类中的哪个位置?
/** @jsx React.DOM */
var List = require('../list');
var ActionBar = require('../action-bar');
var BalanceBar = require('../balance-bar');
var Sidebar = require('../sidebar');
var AppBase = React.createClass({
render: function () {
return (
<div className="wrapper">
<Sidebar />
<div className="inner-wrapper">
<ActionBar title="Title Here" />
<BalanceBar balance={balance} />
<div className="app-content">
<List items={items} />
</div>
</div>
</div>
);
}
});
module.exports = AppBase;
13 回答
https://facebook.github.io/react/docs/react-component.html#componentdidmount
渲染组件后,将调用此方法一次 . 所以你的代码看起来就像这样 .
渲染后,您可以像下面一样指定高度,并可以指定相应反应组件的高度 .
或者您可以使用sass指定每个反应组件的高度 . 指定前2个具有固定宽度的反应分量主分区,然后使用auto指定第三个分量主分区的高度 . 因此,根据第三个div的内容,将分配高度 .
来自ReactDOM.render()文档:
当我需要打印接收大量数据并在画布上绘制的反应组件时,我有奇怪的情况 . 我已经尝试了所有提到的方法,其中没有它们可靠地为我工作,在setTimeout内的requestAnimationFrame我在20%的时间得到空画布,所以我做了以下:
基本上我做了一个requestAnimationFrame的链,不确定是不是这个好主意但是到目前为止我在100%的情况下工作(我使用30作为n变量的值) .
您可以更改状态,然后在setState callback中进行计算 . 根据React文档,这是"guaranteed to fire after the update has been applied" .
这应该在
componentDidMount
或代码中的其他地方(比如在resize事件处理程序中)而不是在构造函数中完成 .这是
window.requestAnimationFrame
的一个很好的替代品,它没有一些用户在这里提到的问题(需要将它与setTimeout
组合或多次调用) . 例如:我实际上遇到了类似行为的问题,我在一个Component中使用它的id属性渲染一个视频元素,所以当RenderDOM.render()结束时,它会加载一个插件,需要id才能找到占位符而无法找到它 .
componentDidMount()里面的0ms的setTimeout修复了它:)
根据我的经验,
window.requestAnimationFrame
不足以确保从componentDidMount
完全渲染/重新完成DOM . 我运行的代码在componentDidMount
调用之后立即访问DOM,并且仅使用window.requestAnimationFrame
将导致元素存在于DOM中;然而,由于尚未发生回流,因此对元素's dimensions aren'的更新反映出来了 .唯一真正可行的方法是将我的方法包装在
setTimeout
和window.requestAnimationFrame
中,以确保React 's current call stack gets cleared before registering for the next frame'呈现 .如果我不得不推测为什么会发生这种情况/必要,我可以看到React批处理DOM更新,而不是直到当前堆栈完成后才将更改应用到DOM .
最后,如果您在React回调之后使用的代码中使用DOM测量,则可能需要使用此方法 .
使用
componentDidUpdate
或componentDidMount
的一个缺点是它们实际上是在完成dom元素绘制之前执行的,但是在它们之后执行它们 .比如说,如果你需要将node.scrollHeight设置为渲染的node.scrollTop,那么React的DOM元素可能还不够 . 你需要等到元素完成后才能达到它们的高度 .
解:
使用
requestAnimationFrame
确保在绘制新渲染的对象后运行代码使用
ES6
类而不是React.createClass
进行一些更新另外 - 检查React组件生命周期方法:https://facebook.github.io/react/docs/react-component.html#the-component-lifecycle
每个组件都有很多类似于
componentDidMount
的方法 .componentWillUnmount()
- 组件即将从浏览器DOM中删除我遇到了同样的问题 .
在大多数情况下使用
componentDidMount()
中的hack-ishsetTimeout(() => { }, 0)
工作 .但不是在特殊情况下;我不想使用
ReachDOM findDOMNode
,因为文档说:(来源:https://facebook.github.io/react/docs/react-dom.html#finddomnode)
所以在那个特定的组件中我必须使用
componentDidUpdate()
事件,所以我的代码最终是这样的:然后:
最后,在我的情况下,我不得不删除
componentDidMount
中创建的侦听器:React的生命周期很少在这些情况下有用的方法,列表包括但不限于 getInitialState, getDefaultProps, componentWillMount, componentDidMount 等 .
在你的情况下以及需要与DOM元素交互的情况下,你需要等到dom准备就绪,所以使用 componentDidMount 如下:
另外,有关生命周期反应的更多信息,请查看以下链接:https://facebook.github.io/react/docs/state-and-lifecycle.html
我觉得这个解决方案很脏,但我们走了:
现在我只是坐在这里等待下来的选票 .
对我来说,没有
window.requestAnimationFrame
或setTimeout
的组合产生一致的结果 . 有时它起作用,但并非总是 - 或者有时候为时已晚 .我根据需要循环
window.requestAnimationFrame
来修复它 .(通常为0或2-3次)
关键是
diff > 0
:这里我们可以确切地确定页面何时更新 .