Skip to content

Commit

Permalink
Fix React 19 deprecation warning when accessing child ref pre-19 way (#…
Browse files Browse the repository at this point in the history
…1416)

[#1343] Fix React 19 deprecation warning when accessing child ref pre-19 way

`child.ref` is deprecated, and generates a warning in the console in R19
because refs are now first-class props.

Check the React version at runtime and if `>=19`, access it via the props;
otherwise, keep accessing it as before (a property of the child React element
object).
  • Loading branch information
stefcameron authored Dec 31, 2024
1 parent ffae03a commit e766841
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 47 deletions.
5 changes: 5 additions & 0 deletions .changeset/orange-bananas-laugh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'focus-trap-react': patch
---

Fix deprecation warning in React 19 when accessing ref the pre-v19 way
14 changes: 13 additions & 1 deletion demo/js/demo-defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ class DemoDefaults extends React.Component {

this.mountTrap = this.mountTrap.bind(this);
this.unmountTrap = this.unmountTrap.bind(this);

this.containerEl = null;
}

mountTrap() {
Expand All @@ -24,14 +26,24 @@ class DemoDefaults extends React.Component {
this.setState({ activeTrap: false });
}

// purposely using a ref here to test new React 19 "ref as a prop" behavior
// with fallback to React 18 deprecated behavior
handleCallbackRef(el) {
this.containerEl = el;
this.containerEl?.classList.add('is-active');
}

render() {
const trap = this.state.activeTrap && (
<FocusTrap
focusTrapOptions={{
onDeactivate: this.unmountTrap,
}}
>
<div className="trap is-active">
<div
className="trap is-active"
ref={(el) => this.handleCallbackRef(el)}
>
<p>
Here is a focus trap <a href="#">with</a> <a href="#">some</a>{' '}
<a href="#">focusable</a> parts.
Expand Down
62 changes: 24 additions & 38 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@
"@testing-library/react": "^16.1.0",
"@testing-library/user-event": "^14.5.2",
"@types/jquery": "^3.5.32",
"@types/react": "^18.3.1",
"@types/react-dom": "^18.3.0",
"@types/react": "^19.0.0",
"@types/react-dom": "^19.0.0",
"all-contributors-cli": "^6.26.1",
"babel-jest": "^29.7.0",
"babelify": "^10.0.0",
Expand All @@ -89,8 +89,8 @@
"jest-watch-typeahead": "^2.2.2",
"onchange": "^7.1.0",
"prettier": "^3.4.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"regenerator-runtime": "^0.14.1",
"start-server-and-test": "^2.0.9",
"typescript": "^5.7.2"
Expand Down
25 changes: 21 additions & 4 deletions src/focus-trap-react.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ const React = require('react');
const { createFocusTrap } = require('focus-trap');
const { isFocusable } = require('tabbable');

/**
* The major version of React currently running.
* @type {number}
*/
const reactVerMajor = parseInt(/^(\d+)\./.exec(React.version)?.[1] ?? 0, 10);

/**
* @type {import('../index.d.ts').FocusTrap}
*/
Expand Down Expand Up @@ -391,10 +397,21 @@ class FocusTrap extends React.Component {
const { containerElements } = this.props;

if (child) {
if (typeof child.ref === 'function') {
child.ref(element);
} else if (child.ref) {
child.ref.current = element;
// React 19 moved the `ref` to an official prop
if (reactVerMajor >= 19) {
if (typeof child.props.ref === 'function') {
child.props.ref(element);
} else if (child.props.ref) {
child.props.ref.current = element;
}
} else {
// older versions of React had the `ref` separate from props (still works in R19
// but results in a deprecation warning in Dev builds)
if (typeof child.ref === 'function') {
child.ref(element);
} else if (child.ref) {
child.ref.current = element;
}
}
}

Expand Down

0 comments on commit e766841

Please sign in to comment.