Есть ли какая-либо разница между использованием useRef().current вместо useRef() ?

#javascript #reactjs #react-native

#javascript #reactjs #react-native

Вопрос:

У меня есть вопрос об объявлении ссылок в React с использованием хука useRef .

Есть ли какая-либо разница между этим:

  const inputRef = useRef(null).current;

 ...

 inputRef?.focus();
  

и это:

  const inputRef = useRef(null);
 
 ...

 inputRef.current?.focus();
  

??

В моем коде поведение такое же, но в некоторых ситуациях, при других вариантах использования, у меня разные результаты.

Например:

  const arrayRef = useRef(null);
 arrayRef.current = data; // data is an array of numbers
  

похоже, это не то же самое, что

  const arrayRef = useRef(null).current;
 arrayRef = data;
 
  

Но почему? (Не совсем уверен, что это не одно и то же, но мой код неожиданно работает с использованием второго метода.)

Я был бы очень признателен за вашу помощь. Спасибо.

Комментарии:

1. Это не имеет никакого смысла, useRef(null).current потому что вы не можете ничего назначить ссылке (как вы указали)? Показать больше контекста.

2. Ссылка — это объект со current свойством. Это current значение может измениться, и поэтому объект ref является удобной оболочкой вокруг этого изменяющегося значения, поэтому вы можете передавать ССЫЛКУ на значение в своем приложении, а не просто передавать значение. Когда вы используете current вместо объекта, вы разворачиваете ссылку, и теперь это просто обычное значение. Если оно изменится, вы можете не получить это изменение везде, где вы используете ссылку, потому что вы ссылаетесь на значение, а не на исходную ссылку. Не разворачивайте его, просто передайте ссылку и используйте ref.current для доступа к значению, когда вам нужно.

3. Есть причина, по которой разработчики в React решили сделать это таким образом. Не нарушайте его.

4. @Raul — хороший! Это особый случай. Сама ссылка в этом компоненте никогда не будет переназначена, а значение, которое она содержит (анимированное значение), обрабатывается с помощью других механизмов.

5. @Raul — учитывается контекст. С учетом контекста становится очень ясно и очевидно, почему код написан именно так.

Ответ №1:

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

Для быстрого примера:

 const Foo = () => {
  const inputRef = useRef(null);
  useEffect(() => {
    window.addEventListener('custom-focus-the-input', () => {
      inputRef.current.focus();
    });
  }, []);
  return (
    <input ref={inputRef} />
  );
};
  

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

Кроме того, чтобы ссылка была .current назначена правильно, вы должны поместить саму ссылку в возвращаемый JSX — не помещайте .current значение в JSX, потому что это не приведет к изменению .current свойства ссылки.


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

Ответ №2:

useRef (как и почти все перехватчики react) эффективно предоставляет переменную экземпляра чему-то, у чего нет экземпляра (функциональный компонент не поддерживается экземпляром — это функция, но react отслеживает его жизненный цикл с помощью fiber и другой классной магии).

Теперь, когда вы знаете, что это просто переменная экземпляра, становится ясно, что переменные экземпляра полезны только в том случае, если им можно что-то назначить.

В приведенном вами контексте:

 const animatedOpacity = useRef(new Animated.Value(0)).current;
  

Переменной экземпляра присваивается Animated.Value . Его никогда не нужно переназначать, потому Animated.Value что (который является current свойством ссылки) обрабатывается / переназначается с помощью других функций, например Animated.timing .