
React18 String Refs
- 746 installs
- 37.1k repo stars
- Updated July 28, 2026
- github/awesome-copilot
react18-string-refs migrates string refs and this.refs to React.createRef in class components.
About
React 18 String Refs Migration converts ref="name" JSX and this.refs.name accessors to React.createRef fields and ref={this.refName} bindings. String refs warn in React 18.3.1 and are removed in React 19, matching the deprecation timeline of other legacy APIs. A pattern map routes single refs, multiple refs, list refs, callback refs, and forwarded child refs to references/patterns.md sections. Grep commands find both JSX string ref assignments and this.refs usage that must migrate as pairs within each component. The three-step rule adds a createRef class field, updates JSX ref binding, and replaces this.refs.name with this.refName.current everywhere.
- String refs warn in React 18.3.1 and are removed in React 19.
- Migrate ref="name" and this.refs.name together per component.
- Pattern map covers single, multiple, list, callback, and forwarded refs.
- Grep commands find JSX string refs and this.refs accessors.
- Three-step rule: createRef field, JSX ref binding, .current accessor.
React18 String Refs by the numbers
- 746 all-time installs (skills.sh)
- +18 installs in the week ending Jul 17, 2026 (Skillselion tracking)
- Ranked #458 of 2,277 Frontend Development skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Jul 28, 2026 (Skillselion catalog sync)
react18-string-refs capabilities & compatibility
- Capabilities
- string ref to createref three step migration rul · grep discovery for jsx refs and this.refs pairs · single, multiple, list, callback, and forwarded · react 18.3.1 warning and react 19 removal timeli · reference routing to patterns.md per ref shape
- Use cases
- refactoring · testing
What react18-string-refs says it does
String refs (`ref="myInput"` + `this.refs.myInput`) were deprecated in React 16.3, warn in React 18.3.1, and are **removed in React 19**.
Both should be migrated together - find the `ref="name"` and the `this.refs.name` accesses for each component as a pair.
npx skills add https://github.com/github/awesome-copilot --skill react18-string-refsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 746 |
|---|---|
| repo stars | ★ 37.1k |
| Security audit | 3 / 3 scanners passed |
| Last updated | July 28, 2026 |
| Repository | github/awesome-copilot ↗ |
How do I replace ref="name" and this.refs usage before React 19 removes string refs?
Migrate React string refs and this.refs accessors to React.createRef in class components before React 19 removal.
Who is it for?
Class components still using string refs or this.refs during React 18.3.1 upgrades.
Skip if: Skip for function components using useRef only, legacy context, or Enzyme test rewrites.
When should I use this skill?
grep finds ref=" in JSX or this.refs. accessors in class component source.
What you get
Paired grep discovery and createRef migration for single, multiple, list, and forwarded ref patterns.
- createRef()-based class components
- Updated ref access patterns
Files
React 18 String Refs Migration
String refs (ref="myInput" + this.refs.myInput) were deprecated in React 16.3, warn in React 18.3.1, and are removed in React 19.
Quick Pattern Map
| Pattern | Reference |
|---|---|
| Single ref on a DOM element | → patterns.md#single-ref |
| Multiple refs in one component | → patterns.md#multiple-refs |
| Refs in a list / dynamic refs | → patterns.md#list-refs |
| Callback refs (alternative approach) | → patterns.md#callback-refs |
| Ref passed to a child component | → patterns.md#forwarded-refs |
Scan Command
# Find all string ref assignments in JSX
grep -rn 'ref="' src/ --include="*.js" --include="*.jsx" | grep -v "\.test\."
# Find all this.refs accessors
grep -rn "this\.refs\." src/ --include="*.js" --include="*.jsx" | grep -v "\.test\."Both should be migrated together - find the ref="name" and the this.refs.name accesses for each component as a pair.
The Migration Rule
Every string ref migrates to React.createRef():
1. Add refName = React.createRef(); as a class field (or in constructor) 2. Replace ref="refName" → ref={this.refName} in JSX 3. Replace this.refs.refName → this.refName.current everywhere
Read references/patterns.md for the full before/after for each case.
String Refs - All Migration Patterns
Single Ref on a DOM Element {#single-ref}
The most common case - one ref to one DOM node.
// Before:
class SearchBox extends React.Component {
handleSearch() {
const value = this.refs.searchInput.value;
this.props.onSearch(value);
}
focusInput() {
this.refs.searchInput.focus();
}
render() {
return (
<div>
<input ref="searchInput" type="text" placeholder="Search..." />
<button onClick={() => this.handleSearch()}>Search</button>
</div>
);
}
}// After:
class SearchBox extends React.Component {
searchInputRef = React.createRef();
handleSearch() {
const value = this.searchInputRef.current.value;
this.props.onSearch(value);
}
focusInput() {
this.searchInputRef.current.focus();
}
render() {
return (
<div>
<input ref={this.searchInputRef} type="text" placeholder="Search..." />
<button onClick={() => this.handleSearch()}>Search</button>
</div>
);
}
}---
Multiple Refs in One Component {#multiple-refs}
Each string ref becomes its own named createRef() field.
// Before:
class LoginForm extends React.Component {
handleSubmit(e) {
e.preventDefault();
const email = this.refs.emailField.value;
const password = this.refs.passwordField.value;
this.props.onSubmit({ email, password });
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<input ref="emailField" type="email" />
<input ref="passwordField" type="password" />
<button type="submit">Log in</button>
</form>
);
}
}// After:
class LoginForm extends React.Component {
emailFieldRef = React.createRef();
passwordFieldRef = React.createRef();
handleSubmit(e) {
e.preventDefault();
const email = this.emailFieldRef.current.value;
const password = this.passwordFieldRef.current.value;
this.props.onSubmit({ email, password });
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<input ref={this.emailFieldRef} type="email" />
<input ref={this.passwordFieldRef} type="password" />
<button type="submit">Log in</button>
</form>
);
}
}---
Refs in a List / Dynamic Refs {#list-refs}
String refs in a map/loop - the most tricky case. Each item needs its own ref.
// Before:
class TabPanel extends React.Component {
focusTab(index) {
this.refs[`tab_${index}`].focus();
}
render() {
return (
<div>
{this.props.tabs.map((tab, i) => (
<button key={tab.id} ref={`tab_${i}`}>
{tab.label}
</button>
))}
</div>
);
}
}// After - use a Map to store refs dynamically:
class TabPanel extends React.Component {
tabRefs = new Map();
getOrCreateRef(id) {
if (!this.tabRefs.has(id)) {
this.tabRefs.set(id, React.createRef());
}
return this.tabRefs.get(id);
}
focusTab(index) {
const tab = this.props.tabs[index];
this.tabRefs.get(tab.id)?.current?.focus();
}
render() {
return (
<div>
{this.props.tabs.map((tab) => (
<button key={tab.id} ref={this.getOrCreateRef(tab.id)}>
{tab.label}
</button>
))}
</div>
);
}
}Alternative - callback ref for lists (simpler):
class TabPanel extends React.Component {
tabRefs = {};
focusTab(index) {
this.tabRefs[index]?.focus();
}
render() {
return (
<div>
{this.props.tabs.map((tab, i) => (
<button
key={tab.id}
ref={el => { this.tabRefs[i] = el; }} // callback ref stores DOM node directly
>
{tab.label}
</button>
))}
</div>
);
}
}
// Note: callback refs store the DOM node directly (not wrapped in .current)
// this.tabRefs[i] is the element, not this.tabRefs[i].current---
Callback Refs (Alternative to createRef) {#callback-refs}
Callback refs are an alternative to createRef(). They're useful for lists (above) and when you need to run code when the ref attaches/detaches.
// Callback ref syntax:
class MyComponent extends React.Component {
// Callback ref - called with the element when it mounts, null when it unmounts
setInputRef = (el) => {
this.inputEl = el; // stores the DOM node directly (no .current needed)
};
focusInput() {
this.inputEl?.focus(); // direct DOM node access
}
render() {
return <input ref={this.setInputRef} />;
}
}When to use callback refs vs createRef:
createRef()- for a fixed number of refs known at component definition time (most cases)- Callback refs - for dynamic lists, when you need to react to attach/detach, or when the ref might change
Important: Inline callback refs (defined in render) re-create a new function on every render, which causes the ref to be called with null then the element on each render cycle. Use a bound method or class field arrow function instead:
// AVOID - new function every render, causes ref flicker:
render() {
return <input ref={(el) => { this.inputEl = el; }} />; // inline - bad
}
// PREFER - stable reference:
setInputRef = (el) => { this.inputEl = el; }; // class field - good
render() {
return <input ref={this.setInputRef} />;
}---
Ref Passed to a Child Component {#forwarded-refs}
If a string ref was passed to a custom component (not a DOM element), the migration also requires updating the child.
// Before:
class Parent extends React.Component {
handleClick() {
this.refs.myInput.focus(); // Parent accesses child's DOM node
}
render() {
return (
<div>
<MyInput ref="myInput" />
<button onClick={() => this.handleClick()}>Focus</button>
</div>
);
}
}
// MyInput.js (child - class component):
class MyInput extends React.Component {
render() {
return <input className="my-input" />;
}
}// After:
class Parent extends React.Component {
myInputRef = React.createRef();
handleClick() {
this.myInputRef.current.focus();
}
render() {
return (
<div>
{/* React 18: forwardRef needed. React 19: ref is a direct prop */}
<MyInput ref={this.myInputRef} />
<button onClick={() => this.handleClick()}>Focus</button>
</div>
);
}
}
// MyInput.js (React 18 - use forwardRef):
import { forwardRef } from 'react';
const MyInput = forwardRef(function MyInput(props, ref) {
return <input ref={ref} className="my-input" />;
});
// MyInput.js (React 19 - ref as direct prop, no forwardRef):
function MyInput({ ref, ...props }) {
return <input ref={ref} className="my-input" />;
}---
Related skills
How it compares
Pick react18-string-refs over generic React upgrade guides when the blocker is specifically deprecated string refs inside class components rather than hooks adoption.
FAQ
Are string refs supported in React 19?
No. They warn in React 18.3.1 and are removed in React 19.
Must I update JSX and JS together?
Yes. Migrate each ref="name" and its this.refs.name accesses as a pair per component.
How handle refs in a list?
See references/patterns.md list-refs section; list refs are a common migration trap.
Is React18 String Refs safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.