Skip to content

[BUG] ref function gets called twice on update (but not on first mount), first call with null value. #9328

@trusktr

Description

@trusktr

Do you want to request a feature or report a bug?

bug

What is the current behavior?

ref functions get called twice on update (but not on first mount).

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://jsfiddle.net or similar (template: https://jsfiddle.net/84v837e9/).

I have some code like this:

render() {
  const frames = []
  frames.length = this.props.totalFrames

  for (let i=0, l=frames.length; i<l; i+=1)
      frames[i] = i

  this.frames = []

  return (
      <div>
          {frames.map(frame =>
              <div className="frame" key={frame} ref={el => {this.frames.push(el)}}>
              </div>
          )}
      </div>
  )
}

In componentDidMount, I can verify that this.frames contains this.props.totalFrames.

However, on componentDidUpdate, this.frames has a length of double this.props.totalFrame, where the first half of the items are all null. This means that subsequent render calls after the first are first passing null into the ref={el => {this.frames.push(el)} function for each element followed by the correct non-null values.

For example, if this.props.totalFrames is 3, then we observe this:

componentDidMount() {
  console.log(this.frames)
  // output:
  // [div, div, div]
}

componentDidUpdate() {
  console.log(this.frames)
  // output:
  // [null, null, null, div, div, div]
}

where this.frames is always twice as expected.

What is the expected behavior?

The array should not contain null values, only the divs.

NOTE, render() is not being called more than once, and I am setting this.frames to a new array inside render, then componentDidUpdate shows that it has double the length, with the first half of the values all null.

It seems like React is calling the ref functions one time too many for each frame element, the first call with a null value, the second call with the expected value.

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?

React 15.4.2

Workaround

As a workaround, I can simply and consistently filter() the null values out before interacting with the array.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions