Демистификация функциональных компонентов React: понимание ссылок и альтернатив

Функциональные компоненты React приобрели огромную популярность благодаря своей простоте и возможности повторного использования. Однако одним из ограничений функциональных компонентов является то, что им нельзя присваивать ссылки. Это означает, что попытки получить доступ к ссылке непосредственно внутри функционального компонента потерпят неудачу. Но не волнуйтесь! В этой статье мы рассмотрим, почему функциональным компонентам нельзя давать ссылки, и углубимся в различные методы и альтернативы для достижения аналогичной функциональности. Итак, приступим!

Понимание ограничений:
Чтобы понять, почему функциональным компонентам нельзя давать ссылки, нам нужно взглянуть на фундаментальное различие между функциональными компонентами и компонентами классов в React. Компоненты класса имеют экземпляр, который может содержать ссылки на элементы DOM или другие компоненты. С другой стороны, функциональные компоненты не имеют состояния и не имеют экземпляров. Ссылки в React – это способ прямой ссылки на элементы или компоненты DOM, а поскольку функциональные компоненты не имеют экземпляров, им нельзя напрямую назначать ссылки.

Метод 1: пересылка ссылок
Пересылка ссылок — это метод, который позволяет передавать ссылку от родительского компонента дочернему компоненту, обеспечивая доступ к узлу DOM дочернего компонента. Для этого мы используем функцию React.forwardRefи обертываем дочерний компонент. Вот пример:

const ChildComponent = React.forwardRef((props, ref) => {
  return <input ref={ref} />;
});
const ParentComponent = () => {
  const inputRef = React.useRef(null);
  // Accessing the child component's ref
  React.useEffect(() => {
    inputRef.current.focus();
  }, []);
  return <ChildComponent ref={inputRef} />;
};

Метод 2: ссылки обратного вызова
Другой подход — использовать ссылки обратного вызова. С помощью этого метода мы определяем функцию обратного вызова, которая получает экземпляр элемента или компонента в качестве аргумента. Вот пример:

const ParentComponent = () => {
  let inputRef = null;
  // Callback function to store the ref
  const setInputRef = (ref) => {
    inputRef = ref;
  };
  // Accessing the ref
  React.useEffect(() => {
    if (inputRef) {
      inputRef.focus();
    }
  }, []);
  return <input ref={setInputRef} />;
};

Метод 3: использование хуков
Встроенные хуки React также можно использовать для достижения аналогичной функциональности. Например, хук useImperativeHandleпозволяет предоставлять определенные функции или свойства дочернего компонента его родительскому компоненту. Вот пример:

const ChildComponent = React.forwardRef((props, ref) => {
  const inputRef = React.useRef(null);
  // Exposing a focus function to the parent component
  React.useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    },
  }));
  return <input ref={inputRef} />;
});
const ParentComponent = () => {
  const childRef = React.useRef(null);
  // Accessing the exposed function
  React.useEffect(() => {
    if (childRef.current) {
      childRef.current.focus();
    }
  }, []);
  return <ChildComponent ref={childRef} />;
};

Хотя к компонентам функций нельзя напрямую присвоить ссылки, мы исследовали различные методы достижения аналогичной функциональности. Переадресация ссылок, ссылки обратного вызова и использование перехватчиков, таких как useImperativeHandle, предоставляют гибкие решения для доступа и взаимодействия с дочерними компонентами или элементами DOM. Понимая эти альтернативы, вы можете улучшить функциональность и читаемость вашего кода React.