Серия React Hooks] useRef

React.js

предисловие

Поскольку функциональные компоненты React проще в использовании (по сравнению с классовыми компонентами), я сосредоточусь на использовании функциональных компонентов для запуска разработки. В этой серии блогов я поделюсь тем, что узнал об API серии Hook. Серия крючков в основном делится на следующие:

что такое пользаСсылка

useRef возвращает изменяемый объект ref, свойство .current которого инициализируется переданным параметром (initialValue). Возвращенный объект ref сохраняется на протяжении всего времени существования компонента.

Этот ref-объект имеет только одно текущее свойство, и если вы что-то в нем сохраните, его адрес никогда не изменится.

Простой пример

import React, { useRef } from "react";
export default function App() {
  const r = useRef(0);
  console.log(r);
  const add = () => {
    r.current += 1;
    console.log(`r.current:${r.current}`);
  };
  return (
    <div className="App">
      <h1>r的current:{r.current}</h1>
      <button onClick={add}>点击+1</button>
    </div>
  );
}

Я установил r сохранить на немuseRefрезультат и поставить егоlogВведите его и давайте посмотрим, что внутри

>  {current: 0}

внутри находитсяcurrentсвойство, которое содержит 0, который я передал.

Изменения useRef не приводят к автоматическому отображению страницы

Нажмем кнопку вышеcurrent+1 видно, что страница не отображается активно, но новаяcurrentЗначение стало 1

Указывает, что значение текущего свойства изменяется и не будет следоватьuseStateилиuseReducerТо же самое вызывает смену страницы. Как решить эту проблему? Давайте сначала подведем итоги, а потом решим

резюме

  • Мы используемuseCurrentвходящийinitialValueможно сделать вывод, что она становится внутреннейcurrentобъект недвижимости,currentСоответствующее значение атрибутаinitialValue
  • Согласно документации по реакции, вы можете знать, что адрес этого объекта не изменится от начала до конца.
  • Изменения useRef не приводят к автоматическому отображению страницы

прикладное решение

давайте использоватьuseRefСотрудничатьuseEffectимитировать одинComponentDidUpdate

import React, { useEffect, useRef, useState } from "react";
export default function App() {
  const r = useRef(0);
  const [n, setN] = useState(0);
  useEffect(() => {
    r.current += 1;
    if (r.current > 1) {
      console.log("r.current:" + r.current);
      console.log("n:" + n);
    }
  });
  return (
    <div className="App">
      <h1>n:{n}</h1>
      <h1>r.current{r.current}</h1>
      <button
        onClick={() => {
          setN(n + 1);
        }}
      >
        {" "}
        +1
      </button>
    </div>
  );
}

первый результат рендеринга

При нажатии кнопки +1Вы обнаружите, что код выполняется, так что вы можете достичьComponentDidUpdate

ток изменился

В приведенном выше коде видно, чтоcurrentОн изменился, потому что изменилось наше состояние, поэтому отрисовывается и новый ток.

Вы можете понять это как механизм реакции:

Тут порядок тока, мне все равно.

Это состояние изменилось, быстро обновите страницу. Подожди, возьми с собой и это течение.

Таким образом, мы можем установить его вручную, установив состояние, которое нецелесообразно.currentСитуация, когда изменение активно вызывает обновление страницы.

Если вы будете осторожны, вы обнаружите, что значения, отображаемые на странице, не актуальны.currentценность . Причина в том,Effectвсегда вrenderтолько после реализации, и на этот разcurrentтолько что обновился, даreact, это не простоcurrentПовторите просмотр обновления. Так что страница все еще стараяcurrent. Это также подтверждает наш первоначальный вывод

Изменения useRef не приводят к автоматическому отображению страницы

Обычно мы не позволяем текущему показу в представлении, приведенный выше пример просто надеется, что вы заметите тонкую связь между текущим изменением и представлением.

резюме

из-заcurrentСтраница не будет отображаться автоматически, поэтому нам лучше установить поддельное состояние, чтобы вручную установить текущий, который будет обновляться представлением вместе с этим поддельным состоянием.

должен сказать впередRef

ref

В компонентах-хуках ref нельзя использовать напрямую, а официальный сайт даже не рекомендует использовать ref в компонентах-классах. Но мы можем использовать ref, который в основном используется для перехода к подкомпонентам и получения dom соответствующего подкомпонента. Вот официальная документацияСсылки и функциональные компоненты

Когда использовать ссылки

Вот несколько ситуаций, когда ссылки уместны:

  • Управляйте фокусом, выделением текста или воспроизведением мультимедиа.
  • Запустить принудительную анимацию.
  • Интегрируйте сторонние библиотеки DOM.

Интерпретация официальных примеров

function CustomTextInput(props) {
  // 这里必须声明 textInput,这样 ref 才可以引用它
  const textInput = useRef(null);//创建一个包含current属性的对象

  console.log(textInput);
  function handleClick() {
    textInput.current.focus();
  }

  return (
    <div>
      <input type="text" ref={textInput} />//挂到内部dom上
      <input type="button" value="Focus the text input" onClick={handleClick} />
    </div>
  );
}

Советы: обратите внимание, что этот пример не используетсяfowardRef, потому что ref не используется в дочерних компонентах, а только внутри функциональных компонентов

Мы можем найти это, просто положивrefПовесив элемент реакции, вы можете получить его dom.

Есть два шага

  • useRefСоздаватьrefобъект
  • ref={xx}висеть наreactэлемент

После этого элемент можно использовать. Официальный пример — захватить элемент и сфокусировать его, нажав кнопку. Теперь мы примерно понимаем, как используются ссылки.

Использовать ref для дочерних компонентов

Вышеупомянутый метод нельзя использовать непосредственно для дочерних компонентов, возможно, вы бы написали так

<Child ref={textInput} />

Но это все еще не может получить DOM дочернего компонента, нам нужно использоватьforwardRefПри совместном использовании приведенный выше пример можно записать так:

function CustomTextInput(props) {
  // 这里必须声明 textInput,这样 ref 才可以引用它
  const textInput = useRef(null);

  console.log(textInput);
  function handleClick() {
    textInput.current.focus();
  }
  return (
    <div>
      <Child ref={textInput} />  //**依然使用ref传递**
      <input type="button" value="Focus the text input" onClick={handleClick} />
    </div>
  );
}
const Child = forwardRef((props, ref) => {  //** 看我 **
  return <input type="text" ref={ref} />;//** 看我挂到对应的dom上 **
});

вышеизложенное черезforwardRefПучокChildФункция оборачивается, а затем передается второй параметрrefпоследнее креплениеref={ref}Таким образом, вы можете получить соответствующий DOM и распечатать его на консоли, чтобы увидеть

current: <input type="text"></input>

Получите элемент DOM дочернего компонента.

резюме

Из приведенного выше примера мы поняли, что использование ref внутри функционального компонента и в дочернем компоненте отличается.

  • Если вы хотите использовать его внутри функции, вы можете напрямую создать и повесить атрибут ref на элемент реакции.
  • Если вы хотите использовать его на дочерних компонентах, в дополнение к шагам выше, вам нужно использоватьforwardRefОберните функцию дочернего компонента, а затем передайте второй параметрref, последнее креплениеrefDOM можно получить обычным образом.

Суммировать

теперь мы знаемuseRefБудет сгенерирован объект, содержащий текущее свойство, которое может сохранять адрес неизменным в течение всего жизненного цикла рендеринга реакции, и мы можем использовать его для выполнения некоторых операций.

Например, создайте глобальные постоянные данные, используйте их для имитацииComponentDidUpdate

Его также можно использовать для монтирования к реагирующему элементу и получения DOM этого элемента. (Здесь внутренние компоненты различительной функции используются непосредственноrefРабота с подкомпонентамиforwardRef)

github

Наконец, я буду продвигать блог на github, который я веду долгое время.

1. От обучения до подведения итогов, запишите важные точки знаний о внешнем интерфейсе, включая углубленное изучение Javascript, протокол HTTP, структуры данных и алгоритмы, принципы браузера, ES6, навыки работы с интерфейсом и т. д.

2. В README есть каталог, в котором можно найти соответствующие точки знаний.

Если это полезно для вас, добро пожаловать, чтобы пометить и подписаться.

Адрес здесь