React:渲染后无法获得正确的元素宽度 [英] React: Can't get correct width of element after render

查看:900
本文介绍了React:渲染后无法获得正确的元素宽度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在React中设置Marquee,如果一段文本大于其容器但是我无法获得容器的正确宽度,即使在组件已渲染之后也是如此。

I'm trying to setup a Marquee in React if a piece of text is greater than its container but I can't get the correct width of the container, even after the component has rendered.

我在另一个回答中读到渲染后的React 代码?,你必须使用我正在尝试的requestAnimationFrame,它仍然无法正常工作。

I read in another answer React "after render" code? that you have to use requestAnimationFrame which I'm trying and it's still not working.

如果我记录容器的宽度,它显示宽度为147px,使用样式表中的min-width设置,但正确的宽度应为320px,使用屏幕最小宽度为600px时的媒体查询。

If I log the width of the container it shows a width of 147px which is set using min-width in the stylesheet but the correct width should be 320px which is set using a media query when the screens min-width is 600px.

这是一个子组件,如果它产生任何差异并且iFrame的宽度为超过600px。

This is a child component, the parent is rendered inside an iFrame if it makes any difference and the iFrame's width is well over 600px.

JS:

module.exports = React.createClass({

  componentDidUpdate: function () {
    // Setup marquee
    this.initMarquee();
  },

  render: function () {
    // Setup marquee
    this.initMarquee();

    var artistName = this.props.artist.artistName;
    var trackName  = this.props.track.trackName;

    return (
      <div className="MV-player-trackData no-select" ref="mvpTrackData">
        <div className="MV-player-trackData-marquee-wrap" ref="mvpMarqueeWrap">
          <div className="MV-player-trackData-marquee" ref="mvpMarquee">
            <a className="MV-player-trackData-link no-select" href={this.props.storeUrl} target="_blank">
              <span id="mvArtistName">{artistName}</span> &ndash; <span id="mvTrackName">{trackName}</span>
            </a>
          </div>
        </div>
      </div>
    )
  },

  initMarquee: function () {
    if ( typeof requestAnimationFrame !== 'undefined' ) {
      //store a this ref, and
      var self = this;
      //wait for a paint to setup marquee
      window.requestAnimationFrame(function() {
        self.marquee();
      });
    }
    else {
      // Suport older browsers
      window.setTimeout(this.marquee, 2000);
    }
  },

  marquee: function () {
    var marquee     = React.findDOMNode(this.refs.mvpMarquee);
    var marqueeWrap = React.findDOMNode(this.refs.mvpMarqueeWrap);

    // If the marquee is greater than its container then animate it
    if ( marquee.clientWidth > marqueeWrap.clientWidth ) {
      marquee.className += ' is-animated';
    }
    else {
      marquee.className = marquee.className.replace('is-animated', '');
    }
  }

});

CSS:

.MV-player-trackData-marquee-wrap {
  height: 20px;
  line-height: 20px;
  min-width: 147px;
  overflow: hidden;
  position: relative;
  width: 100%;

  @media only screen and (min-width : 600px) {
    min-width: 320px;
  }
}

我尝试了很多不同的解决方案,包括< a href =https://www.npmjs.com/package/laidout =nofollow noreferrer> layout 和 react-component-width-mixin 但它们都不起作用。我试过反应组件宽度mixin,因为在我的应用程序的另一部分我试图获得 window.innerWidth 的值,但在渲染后也返回0,除非我设置了暂停超过2秒,不幸的是,由于数据加载和其他回调,有时2秒不够长,所以这可以轻松制动。

I've tried a number of different solutions including laidout and react-component-width-mixin but neither of them work. I tried react component width mixin because in another part of my app I'm trying to get the value of window.innerWidth but that also returns 0 after rendering, unless I set a timeout for around 2 seconds, unfortunately though sometimes 2 seconds isn't long enough due to data loading and other callbacks so this can brake easily.

任何帮助都非常感谢。谢谢。

Any help is really appreciated. Thanks.

更新:
其中一个答案正确指出我应该调用 this.initMarquee (); 在我正在做的 componentDidMount 里面,不幸的是我在测试时粘贴了错误的代码,看看它是否有所作为在内部。正确的代码如下所示:

Update: One of the answers correctly pointed out i should be calling this.initMarquee(); inside componentDidMount which I was doing, unfortunately I pasted the wrong code from when I was testing to see if it made a difference calling it inside render. The correct code looks like this:

componentDidMount: function () {
  // Setup marquee
  this.initMarquee();
},

不幸的是,这也不起作用,我仍然收到不正确的宽度marqueeWrap。

Unfortunately this doesn't work either, I still receive the incorrect width for marqueeWrap.

更新:24/06/2015
只是为了澄清,这是选框效果我试图实现,只有当文本比它的容器大时才会实现,因为当它不大时,它是无意义的滚动它。

Update: 24/06/2015 Just to clarify, this is the marquee effect I'm trying to achieve, only when the text is bigger than its container as it's pointless scrolling it when it is not bigger.

此处还有指向的链接来自React团队的Github问题,讲述了React在浏览器绘制之前呈现的原因。 - 所以在这种情况下,我想知道如何可靠地获得有问题元素的宽度。

Also here is a link to a Github Issue from the React team speaking about why React renders before the browser paints. - So as that is the case, I want to know how do I reliably get the width of the element in question.

推荐答案

可能出现的一个问题是,当componentDidMount触发时,您的CSS尚未加载。这可能发生在webpack中,包括你的包中也包含你的js的css,即使你已经在项目中的组件之前包含了css。

One possible problem that can occur is that your CSS has not loaded yet when componentDidMount fires. This can happen with webpack and including the css in your bundle that also contains your js even if you have included the css before your component in the project.

这篇关于React:渲染后无法获得正确的元素宽度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆