React.js:初始渲染时引用不可用
Posted
技术标签:
【中文标题】React.js:初始渲染时引用不可用【英文标题】:React.js: Refs are not available on initial render 【发布时间】:2014-04-09 21:44:00 【问题描述】:我想在组件的根 DOM 元素中间放置一个圆圈:
var App = React.createClass(
render: function()
return <svg ref="svg">
<circle r="9" cx=this.centerX() cy="15"/>
</svg>;
,
centerX: function()
var svg = this.refs.svg.getDOMNode();
return svg.offsetLeft + Math.round(svg.offsetWidth / 2);
);
http://jsfiddle.net/NV/94tCQ/
鸡和蛋的问题发生在这里:this.refs
在第一次渲染时未定义。解决这个问题的最佳方法是什么?我不希望引用外部 DOM 节点(例如 document.body
)。
【问题讨论】:
【参考方案1】:不是refs
没有定义,而是您在尝试生成 DOM 的同时尝试访问它。 this.refs.svg.getDOMNode
不会返回任何内容,因为该组件在 render
中没有真正的 DOM 表示。
为了保持更多的 React-y,我会将 cx
移动到组件的状态,并在元素渲染到 DOM 后更新它:
var App = React.createClass(
componentDidMount: function()
var svg = this.refs.svg.getDOMNode();
this.setState(
cx: svg.offsetLeft + Math.round(svg.offsetWidth / 2)
);
,
getInitialState:
return
cx: 0
;
,
render: function()
return (
<svg ref="svg">
<circle r="9" cx=this.state.cx cy="15" />
</svg>
);
);
【讨论】:
当然,如果您知道 svg 元素的尺寸,您还可以计算渲染中的正确中心,以避免必须从 DOM 中读取。在这种情况下它不会特别明显,但为了性能,最好避免从 DOM 读取并尽可能地重新渲染。 @BenAlpert 好点。尽管在这种情况下,代码引用了offsetLeft
,它是相对于 DOM 节点最近定位的父节点的。在将 offsetParent 和此元素都渲染到 DOM 之前,不可能获得该数字。这在 CSS 中可能会更好地解决,但考虑到原始帖子中的代码,这似乎是最合适的。
我完全同意。我的评论主要针对原始海报,作为可选的增强功能。【参考方案2】:
解决此问题的一种巧妙方法是,当它尚未插入 DOM 时返回一个虚拟值,当它插入时(使用 componentDidMount)然后重新绘制元素。
centerX: function()
if (!this.refs || !this.refs.svg)
return 0;
var svg = this.refs.svg.getDOMNode();
return svg.offsetLeft + Math.round(svg.offsetWidth / 2);
,
componentDidMount: function()
this.forceUpdate();
http://jsfiddle.net/vjeux/94tCQ/4/
【讨论】:
这看起来确实很老套。 :)以上是关于React.js:初始渲染时引用不可用的主要内容,如果未能解决你的问题,请参考以下文章
Gatsby:在使用带有 JavaScript 的 Bootstrap 组件构建项目时,服务器端渲染期间“文档”不可用