# String Refs - All Migration Patterns
## Single Ref on a DOM Element {#single-ref}
The most common case - one ref to one DOM node.
```jsx
// Before:
class SearchBox extends React.Component {
handleSearch() {
const value = this.refs.searchInput.value;
this.props.onSearch(value);
}
focusInput() {
this.refs.searchInput.focus();
}
render() {
return (
);
}
}
// 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.
```jsx
// 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 ;
}
}
```
**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:
```jsx
// AVOID - new function every render, causes ref flicker:
render() {
return { this.inputEl = el; }} />; // inline - bad
}
// PREFER - stable reference:
setInputRef = (el) => { this.inputEl = el; }; // class field - good
render() {
return ;
}
```
---
## 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.
```jsx
// Before:
class Parent extends React.Component {
handleClick() {
this.refs.myInput.focus(); // Parent accesses child's DOM node
}
render() {
return (