Repository: facebook/react
File: packages/react/src/jsx/ReactJSXElement.js (JavaScript)

Code before:
  }

  let propName;

  // Original props are copied
  const props = assign({}, element.props);

  // Reserved names are extracted
  let key = element.key;
  let ref = enableRefAsProp ? null : element.ref;

  // Owner will be preserved, unless ref is overridden
  let owner = !__DEV__ && disableStringRefs ? undefined : element._owner;

  if (config != null) {
    if (hasValidRef(config)) {
      if (!enableRefAsProp) {
        // Silently steal the ref from the parent.
        ref = config.ref;
        if (!disableStringRefs) {
          let refOwner = owner;
          if (refOwner == null) {
            // fall back to the current owner
            refOwner = ReactSharedInternals.owner;
          }
          ref = coerceStringRef(ref, refOwner, element.type);
        }
      }
      owner = ReactSharedInternals.owner;
    }
    if (hasValidKey(config)) {
      if (__DEV__) {
        checkKeyStringCoercion(config.key);
      }
      key = '' + config.key;
    }

    // Remaining properties override existing props
    let defaultProps;
    if (
      !disableDefaultPropsExceptForClasses &&
      element.type &&
      element.type.defaultProps
    ) {
      defaultProps = element.type.defaultProps;
    }
    for (propName in config) {
      if (
        hasOwnProperty.call(config, propName) &&
        // Skip over reserved prop names
        propName !== 'key' &&

Review comment (suggestion):
I think the proper fix it to move line 881 to the top of the `hasValidRef` block? 

This comment suggests that the current owner should be used whenever a new ref is provided:

```js
  // Owner will be preserved, unless ref is overridden
```

Code after:
  }

  let propName;

  // Original props are copied
  const props = assign({}, element.props);

  // Reserved names are extracted
  let key = element.key;
  let ref = enableRefAsProp ? null : element.ref;

  // Owner will be preserved, unless ref is overridden
  let owner = !__DEV__ && disableStringRefs ? undefined : element._owner;

  if (config != null) {
    if (hasValidRef(config)) {
      owner = ReactSharedInternals.owner;
      if (!enableRefAsProp) {
        // Silently steal the ref from the parent.
        ref = config.ref;
        if (!disableStringRefs) {
          ref = coerceStringRef(ref, owner, element.type);
        }
      }
    }
    if (hasValidKey(config)) {
      if (__DEV__) {
        checkKeyStringCoercion(config.key);
      }
      key = '' + config.key;
    }

    // Remaining properties override existing props
    let defaultProps;
    if (
      !disableDefaultPropsExceptForClasses &&
      element.type &&
      element.type.defaultProps
    ) {
      defaultProps = element.type.defaultProps;
    }
    for (propName in config) {
      if (
        hasOwnProperty.call(config, propName) &&
        // Skip over reserved prop names
        propName !== 'key' &&
        (enableRefAsProp || propName !== 'ref') &&
        // ...and maybe these, too, though we currently rely on them for
        // warnings and debug information in dev. Need to decide if we're OK
        // with dropping them. In the jsx() runtime it's not an issue because
        // the data gets passed as separate arguments instead of props, but