Skip to content

bug: ref callback order #3564

Open
Open
@George-Payne

Description

@George-Payne

Prerequisites

Stencil Version

2.17.4

Current Behavior

When using a ref callback, new refs are given before old refs are nullified.

For example, if you change a key on an element, the ref will be called with the new div before it is called with null

my-component.tsx
import { Component, h, State } from '@stencil/core';

let i = 0;
const nextKey = () => `key-${i++}`;

@Component({
  tag: 'my-component',
  styleUrl: 'my-component.css',
  shadow: true,
})
export class MyComponent {
  @State() currentKey: string = nextKey();

  componentDidLoad() {
    setInterval(() => {
      this.currentKey = nextKey();
    }, 3_000);
  }

  render() {
    return (
      <div ref={this.captureDiv} key={this.currentKey}>
        {this.currentKey}
      </div>
    );
  }

  private captureDiv = (r: HTMLDivElement | null) => {
    console.log(this.currentKey, r);
  };
}

Will give:

key-0 <div>​key-0​</div>​
key-1 <div>​key-1​</div>​
key-1 null
key-2 <div>​key-2​</div>​
key-2 null
key-4 <div>​key-4​</div>​
key-4 null
key-5 <div>​key-5​</div>​
key-5 null
// etc

This is potentially problematic, as if you track a single ref:

private captureDiv = (r?: HTMLDivElement) => {
    this.divRef = r;
};

The reference will be set to null after the new ref is given.

Expected Behavior

Old refs should be nullified before new refs are given.

key-0 <div>​key-0​</div>​
key-1 null
key-1 <div>​key-1​</div>​
key-2 null
key-2 <div>​key-2​</div>​
key-4 null
key-4 <div>​key-4​</div>​
key-5 null
key-5 <div>​key-5​</div>​
// etc

For reference, equivalent code in react will give null before the next ref is given:

https://jsfiddle.net/yk23w1dj/16/

"key-0", "DIV"
"key-1", "null"
"key-1", "DIV"
"key-2", "null"
"key-2", "DIV"
"key-3", "null"
"key-3", "DIV"

// etc

Steps to Reproduce

  1. clone reproduction repo
  2. switch to branch https://github.com/George-Payne/stencil-bug-reproductions/tree/ref-key-order
  3. npm install
  4. npm run dev

Open in browser and view console:

key-0 <div>​key-0​</div>​
key-1 null
key-1 <div>​key-1​</div>​
key-2 null
key-2 <div>​key-2​</div>​
key-4 null
key-4 <div>​key-4​</div>​
key-5 null
key-5 <div>​key-5​</div>​
// etc
  1. Note that the "new" ref is given before the previous one is nullified.
  2. Same behaviour for production build: npm run prod

Code Reproduction URL

https://github.com/George-Payne/stencil-bug-reproductions/tree/ref-key-order

Additional Information

Possibly related to: #3253

Metadata

Metadata

Assignees

No one assigned

    Labels

    Bug: ValidatedThis PR or Issue is verified to be a bug within Stencil

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions