How to fix Function components cannot have string refs in React
This error occurs when using deprecated string refs in React function components. String refs are legacy syntax that React removed in favor of useRef() hook and createRef() API for better type safety and composability.
Quick fix
Fixes Function components cannot have string refs
# Search for ref=" patterns
grep -r 'ref="[^{]' src/
# Or use your editor's search functionality
# Look for patterns like: ref="myRef"- Identify all string ref usage in your codebase
- Convert string refs to callback refs in class components
- Use createRef API for class components
- Convert to useRef hook in function components
# Search for ref=" patternsgrep -r 'ref="[^{]' src/# Or use your editor's search functionality# Look for patterns like: ref="myRef"Function components cannot have string refs
What this error means
String refs are an older API where the ref attribute accepts a string value, like ref="textInput", and the DOM node is accessed via this.refs.textInput. This pattern was deprecated in March 2018 (React v16.3.0) because it has several fundamental issues. The primary problems with string refs include: they don't work with static analysis tools like Flow or TypeScript, they can lead to hard-to-debug bugs when the same string ref is accidentally used in multiple places (causing them to overwrite each other), they require React to keep track of the currently executing component which impacts performance, and they don't compose well in modern React patterns. React recommends migrating to either callback refs or the createRef/useRef APIs, which provide better type safety, performance, and debugging capabilities. In React 19 and beyond, string refs will be completely removed from the framework.
Typical symptoms
- Warning message "Component contains the string ref" appears in console
- ESLint rule "react/no-string-refs" is triggered during development
- Warning states "Support for string refs will be removed in a future major release"
- Function components fail with "Function components cannot have string refs" error
- Code using this.refs.refName pattern shows deprecation warnings
- Build warnings appear when upgrading to React 19 or newer
- Static analysis tools like Flow or TypeScript cannot properly type-check string refs
Common causes
- Using legacy ref="stringValue" syntax instead of modern ref patterns
- Accessing refs via this.refs.refName in class components
- Migrating old React codebases (pre-16.3.0) without updating ref patterns
- Copy-pasting code examples from outdated tutorials or documentation
- Using third-party libraries that still use deprecated string refs internally
- Not updating dependencies that contain string ref usage
- Following React Native code examples written before 2018
- Using component libraries built before React 16.3.0 without updates
How to fix "Function components cannot have string refs"
Search for string refs in your project to understand the scope of changes needed:
# Search for ref=" patterns
grep -r 'ref="[^{]' src/
# Or use your editor's search functionality
# Look for patterns like: ref="myRef"Common locations include form inputs, DOM node references, and third-party component integrations.
Replace string refs with callback refs that assign to instance properties:
// Before (deprecated)
class MyComponent extends React.Component {
handleClick = () => {
this.refs.myInput.focus();
}
render() {
return <input ref="myInput" />;
}
}
// After (callback ref)
class MyComponent extends React.Component {
handleClick = () => {
this.myInput.focus();
}
render() {
return <input ref={el => this.myInput = el} />;
}
}Callback refs receive the element as an argument and you can store it however you like.
For cleaner class component code, use the createRef API introduced in React 16.3:
import React from 'react';
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myInput = React.createRef();
}
handleClick = () => {
// Access via .current property
this.myInput.current.focus();
}
render() {
return <input ref={this.myInput} />;
}
}Note that createRef refs are accessed via the .current property.
For function components, use the useRef hook instead:
import React, { useRef } from 'react';
function MyComponent() {
const myInput = useRef(null);
const handleClick = () => {
myInput.current.focus();
};
return (
<div>
<input ref={myInput} />
<button onClick={handleClick}>Focus Input</button>
</div>
);
}The useRef hook is the standard approach for function components and works with TypeScript.
Replace all instances of this.refs.refName with the new ref pattern:
// Before
this.refs.myInput.value
this.refs.myDiv.scrollTop
// After (callback ref)
this.myInput.value
this.myDiv.scrollTop
// After (createRef/useRef)
this.myInput.current.value
this.myDiv.current.scrollTopRemember that createRef and useRef require accessing the .current property.
Check if any dependencies are causing the warnings:
# Update all dependencies to latest versions
npm update
# Or check for specific outdated packages
npm outdated
# Update specific packages
npm install react-component-name@latestIf a library hasn't been updated, consider filing an issue or finding an alternative package.
Add the react/no-string-refs rule to your ESLint configuration:
// .eslintrc.json
{
"extends": ["react-app"],
"rules": {
"react/no-string-refs": "error"
}
}This ensures string refs won't be accidentally introduced in new code.
Advanced notes
When working with forwarded refs in custom components, you need to use React.forwardRef to properly pass refs through component boundaries. This is particularly important when migrating component libraries from string refs.
For TypeScript projects, createRef and useRef provide much better type inference than string refs ever could. You can type refs like: const myRef = useRef<HTMLInputElement>(null).
In React Native, string refs follow the same deprecation timeline as React for web. The migration path is identical, though you'll be working with native component refs like TextInput instead of DOM elements.
If you're maintaining a large legacy codebase, consider using a codemod tool to automate the migration. The React team has provided codemods for common ref patterns, though manual review is still recommended for complex cases.
For teams upgrading to React 19, note that string refs have been completely removed and will cause runtime errors rather than just warnings. Plan your migration accordingly before upgrading major versions.
Frequently asked questions
- What does "Function components cannot have string refs" mean?
- textInput. 0) because it has several fundamental issues. The primary problems with string refs include: they don't work with static analysis tools like Flow or TypeScript, they can lead to hard-to-debug bugs when the same string ref is accidentally used in multiple places (causing them to overwrite each other), they require React to keep track of the currently executing component which impacts performance, and they don't compose well in modern React patterns.
- How do I fix "Function components cannot have string refs"?
- This error occurs when using deprecated string refs in React function components. String refs are legacy syntax that React removed in favor of useRef() hook and createRef() API for better type safety and composability.
- What causes "Function components cannot have string refs"?
- Using legacy ref="stringValue" syntax instead of modern ref patterns Accessing refs via this.refs.refName in class components Migrating old React codebases (pre-16.3.0) without updating ref patterns
- Is the "Function components cannot have string refs" error serious?
- It is a medium-severity error โ more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- ๐React Official Documentation
- ๐React: Refs and the DOM - Legacy Documentation(Official Docs)
- ๐React 19 Upgrade Guide(Official Docs)
- ๐