4

React Basics: How to Use ForwardRef

 8 months ago
source link: https://www.telerik.com/blogs/react-basics-how-to-use-forwardref
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

React Basics: How to Use ForwardRef

reactt3-light-1200x303.png?sfvrsn=87591c81_3

Learn how to use the forwardRef function in React to expose DOM nodes inside a component to its parent component.

In React, refs are used for storing values that don’t trigger a re-render when updated. We can also assign refs to DOM elements so that we can reference the ref to manipulate the DOM element assigned to the ref.

Refs can also be assigned components, but we need to do one extra step. We need to forward the ref to the DOM element we want to assign or set the value we want to return when the ref is referenced with forwardRef.

In this article, we will look at how to use the forwardRef function to expose DOM nodes that are inside a component.

Basic Usage

We call the forwardRef function with a render function. A render function returns a group of DOM elements or components.

forwardRef is needed to expose a DOM node in a component to its parent component.

For instance, we write:

import { forwardRef, useRef } from "react";

const CustomInput = forwardRef((props, ref) => {
  const { label } = props;
  return (
    <>
      <label>{label}</label>
      <input ref={ref} />
    </>
  );
});

export default function App() {
  const inputRef = useRef();

  return (
    <div>
      <CustomInput label="Name" ref={inputRef} />
      <button onClick={() => inputRef.current.focus()}>focus</button>
    </div>
  );
}
React JSX

to define the CustomInput component.

We allow the CustomInput component to be assigned a ref by calling forwardRef with the render function. The function takes the props of the component and the ref.

We assign the ref parameter value as the value of the input’s ref prop so that the input will be returned as the value of inputRef.current when we reference it in App.

props is the props for the CustomInput component. Therefore, the label prop’s value would be Name.

In App, we create a ref with useRef and assign that as the value of CustomInput's ref prop.

Then we assign the onClick prop of the button to call inputRef.current.focus(), where inputRef.current is the input element within the CustomInput component.

Therefore, when we click the focus button, the input will have focus.

Customize the Value of the Ref

We can customize the value of the ref with the useImperativeHandle hook. useImperativeHandle takes the ref, a callback that returns the value we want for the ref, and an array of dependencies to watch for to trigger the callback to call as arguments.

For instance, we write:

import { forwardRef, useImperativeHandle, useRef } from "react";
import { v4 as uuidv4 } from "uuid";
const CustomInput = forwardRef((props, ref) => {
  const { label } = props;
  const inputRef = useRef(null);

  useImperativeHandle(
    ref,
    () => {
      return {
        focus() {
          inputRef.current.focus();
        },
        scrollIntoView() {
          inputRef.current.scrollIntoView();
        }
      };
    },
    []
  );

  return (
    <>
      <label>{label}</label>
      <div>
        <input ref={inputRef} />
      </div>
    </>
  );
});

export default function App() {
  const inputRef = useRef();

  return (
    <div>
      <div>
        <button onClick={() => inputRef.current.focus()}>focus</button>
        <button onClick={() => inputRef.current.scrollIntoView()}>
          scroll into view
        </button>
      </div>
      {Array(100)
        .fill()
        .map((_, i) => {
          const key = uuidv4();
          return (
            <CustomInput
              key={key}
              label={`Name ${i + 1}`}
              ref={i === 99 ? inputRef : undefined}
            />
          );
        })}
    </div>
  );
}
React JSX

to change CustomInput to call the useImperativeHandle hook.

It takes the ref we want to forward as the first argument. The ref will then be set to the value returned by the callback in the second argument.

We choose to return the focus and scrollIntoView method. focus calls focus on the input element we assigned the inputRef to by setting the ref prop of the input to inputRef.

And in scrollIntoView, we call the input’s scrollIntoView method to scroll the page until the input is visible on the screen.

The third argument is an empty array since we don’t want to return a new value when anything with a reactive value changes, including props and states.

Next, in App, we render 100 CustomInput components. We assign the inputRef in the App component as the ref prop’s value if index i in 99. Otherwise, we don’t assign a ref to it.

Therefore, the last CustomInput rendered, which is the bottommost one, would be assigned inputRef and the rest has no ref assigned to them.

Afterward, we add two buttons. The first button calls inputRef.current.focus() to call focus on the CustomInput that has been assigned App's inputRef.

Likewise, the second button calls scrollIntoView with the same CustomInput. As a result, when we click scrollIntoView, we scroll to the bottom of the page. And when we click focus, the last input is focused on.

Forwarding Refs Through Multiple Components

Refs can be forwarded through multiple components.

For instance, if we write:

import { forwardRef, useRef } from "react";

const CustomInput = forwardRef((props, ref) => {
  const { label } = props;

  return (
    <>
      <label>{label}</label>
      <div>
        <input ref={ref} />
      </div>
    </>
  );
});

const InputGroup = forwardRef((props, ref) => {
  const { label } = props;

  return (
    <>
      <CustomInput ref={ref} label={label} />
      <select>
        <option>foo</option>
        <option>bar</option>
      </select>
    </>
  );
});

export default function App() {
  const inputRef = useRef();

  return (
    <div>
      <div>
        <button onClick={() => inputRef.current.focus()}>focus</button>
      </div>

      <InputGroup label="Name" ref={inputRef} />
    </div>
  );
}
React JSX

to define the InputGroup component, which renders a CustomInput component.

InputGroup is created by calling the forwardRef function so that it can accept the ref prop.

Then we pass the ref to CustomInput by assigning the ref parameter of its render function to CustomInput's ref prop.

And in CustomInput's render function, we assign its ref parameter to the input’s ref prop.

As a result, the App component’s inputRef value is the input element in CustomInput since that’s where the ref is ultimately forwarded to.


How To Bind Any Component to Data in React: One-Way Binding

Learn about useState in this post, which discusses data binding, types, how to utilize useState and useRef to bind data in React, and more.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK