How to fix Warning: Function components cannot have string refs in React
This warning appears when you try to use string refs (like ref="myRef") in a React function component. String refs are a legacy API that only works with class components, and React function components require the useRef hook or callback refs instead.
Quick fix
Fixes Warning: Function components cannot have string refs
// ❌ Before (causes warning)
function MyComponent() {
return <input ref="myInput" />;
}
// ✅ After (correct approach)
import { useRef } from 'react';
function MyComponent() {
const myInputRef = useRef(null);
return <input ref={myInputRef} />;
}- Replace string ref with useRef hook
- Update ref access from this.refs to .current
- Use callback refs for complex scenarios
- Use forwardRef for refs in reusable components
// ❌ Before (causes warning)function MyComponent() {return <input ref="myInput" />;}// ✅ After (correct approach)import { useRef } from 'react';function MyComponent() {const myInputRef = useRef(null);return <input ref={myInputRef} />;}Warning: Function components cannot have string refs
What this error means
This warning occurs because string refs are an older React API pattern that was designed for class components. In class components, you could write `ref="myInput"` and later access the DOM element via `this.refs.myInput`. However, function components don't have a `this` context or instance properties, so they cannot support this pattern. String refs have been considered legacy since React 16.3 (released in 2018) and are likely to be removed in future React versions. React recommends migrating to either the `useRef` hook for function components or callback refs for more complex scenarios. While string refs aren't officially deprecated yet, they're not composable, can lead to hard-to-debug issues when the same string ref is used in multiple places, and don't work with modern React patterns like hooks and function components.
Typical symptoms
- Warning appears in browser console during development
- Component tries to access refs but returns undefined
- String ref attribute (like ref="myElement") is present in function component JSX
- Migration from class component to function component causes ref access to break
- ESLint shows react/no-string-refs warning if configured
Common causes
- Using string ref syntax (ref="refName") in a function component instead of class component
- Converting a class component to function component without updating string refs to useRef
- Copying ref patterns from old React documentation or tutorials written before React 16.3
- Using a third-party component that internally tries to apply string refs to function components
- Attempting to access this.refs in a function component context
How to fix "Warning: Function components cannot have string refs"
Import the useRef hook from React and create a ref object instead of using a string:
// ❌ Before (causes warning)
function MyComponent() {
return <input ref="myInput" />;
}
// ✅ After (correct approach)
import { useRef } from 'react';
function MyComponent() {
const myInputRef = useRef(null);
return <input ref={myInputRef} />;
}The ref object will have a .current property that holds the DOM element once mounted.
Change any code that accesses the ref from the old this.refs pattern to the new .current property:
// ❌ Before (class component pattern)
class MyComponent extends React.Component {
handleClick = () => {
this.refs.myInput.focus();
}
render() {
return (
<>
<input ref="myInput" />
<button onClick={this.handleClick}>Focus</button>
</>
);
}
}
// ✅ After (function component with useRef)
import { useRef } from 'react';
function MyComponent() {
const myInputRef = useRef(null);
const handleClick = () => {
myInputRef.current?.focus();
};
return (
<>
<input ref={myInputRef} />
<button onClick={handleClick}>Focus</button>
</>
);
}Note the optional chaining (?.) to safely access .current in case the ref isn't attached yet.
For dynamic refs or when you need to perform side effects when the ref changes, use callback refs:
import { useState, useCallback } from 'react';
function MyComponent() {
const [inputElement, setInputElement] = useState(null);
// Callback ref - called when element mounts/unmounts
const callbackRef = useCallback((element) => {
if (element) {
setInputElement(element);
element.focus(); // Perform side effect when mounted
}
}, []);
return <input ref={callbackRef} />;
}Callback refs receive the DOM element (or null on unmount) as an argument and give you more control over when refs are set and unset.
If you're building a reusable component that needs to expose a ref to its parent, use React.forwardRef:
import { forwardRef } from 'react';
// ✅ Allows parent to pass ref to underlying input
const CustomInput = forwardRef((props, ref) => {
return <input ref={ref} {...props} />;
});
// Usage in parent component
function ParentComponent() {
const inputRef = useRef(null);
return (
<>
<CustomInput ref={inputRef} />
<button onClick={() => inputRef.current?.focus()}>
Focus Input
</button>
</>
);
}Without forwardRef, function components cannot receive refs as props.
Advanced notes
React 19 Changes: React 19 adds support for function components to receive refs directly without forwardRef, but string refs remain unsupported and should still be avoided.
Multiple Refs: If you need to track multiple dynamic elements (like list items), use an array or Map with callback refs:
function ItemList({ items }) {
const itemRefs = useRef(new Map());
return items.map((item) => (
<div
key={item.id}
ref={(el) => {
if (el) {
itemRefs.current.set(item.id, el);
} else {
itemRefs.current.delete(item.id);
}
}}
>
{item.name}
</div>
));
}ESLint Rule: Enable react/no-string-refs in your ESLint configuration to catch string refs during development:
{
"rules": {
"react/no-string-refs": "error"
}
}Performance Consideration: useRef doesn't cause re-renders when its .current value changes. If you need to trigger re-renders based on ref changes, use callback refs with state as shown in Step 3.
Frequently asked questions
- What does "Warning: Function components cannot have string refs" mean?
- This warning occurs because string refs are an older React API pattern that was designed for class components. myInput. However, function components don't have a this context or instance properties, so they cannot support this pattern.
- How do I fix "Warning: Function components cannot have string refs"?
- This warning appears when you try to use string refs (like ref="myRef") in a React function component. String refs are a legacy API that only works with class components, and React function components require the useRef hook or callback refs instead.
- What causes "Warning: Function components cannot have string refs"?
- Using string ref syntax (ref="refName") in a function component instead of class component Converting a class component to function component without updating string refs to useRef Copying ref patterns from old React documentation or tutorials written before React 16.3
- Is the "Warning: 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 useRef Hook documentation(Official Docs)
- 📖React Refs and the DOM (Legacy Docs)(Official Docs)
- 📝
- 📖ESLint React no-string-refs rule(Official Docs)