React Hooks: Почему.current null для useRef Hooks?

У меня есть простой пример компонента:

function App() {
  const observed = useRef(null);
  console.log(observed.current);

  return (
    <div ref={observed} className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Я ожидаю, что observed.current будет иметь тип элемента и текущий не будет пустым, но элемент div со всеми его свойствами. Мое понимание будет:

  1. Ссылка инициализируется значением null
  2. Null перезаписывается ссылкой

Но, как оказалось, .current остается пустым. Это плохо, так как я хочу передать наблюдаемое в функцию, которая ожидает аргумент типа Element.

https://codesandbox.io/embed/purple-forest-0460k

4 ответа

Ref.current является нулевым, потому что ссылка не устанавливается до тех пор, пока функция не вернется и содержимое будет отображено. Хук useEffect срабатывает каждый раз, когда изменяется значение содержимого переданного ему массива. Мимоходом observed в массиве и путем передачи обратного вызова, который регистрирует observed к консоли можно использовать хук useEffect для выполнения вашей задачи.

  useEffect(() => {
    console.log(observed.current);
  }, [observed]);

Код Песочница

Это то, чем я закончил с тех пор, как позвонил useEffect на rlvRef не охватил все события.

const rlvRef = useRef()
const [refVisible, setRefVisible] = useState(false)

useEffect(() => {
  if (!refVisible) { 
    return
  }
  // detected rendering
}, refVisible)

return (
<RecyclerListView
              ref={el => { rlvRef.current = el; setRefVisible(!!el); }}
... />
)

В то время console.log случается, ref еще не установлен. Попробуйте положить свой console.log в useEffect крючок, и он работает так, как вы хотите.

import React, { useRef, useEffect } from "react";
import ReactDOM from "react-dom";

import "./styles.css";

function App() {
  const observed = useRef(null);

  useEffect(() => {
    console.log(observed.current);
  }, [observed]);

  return (
    <div ref={observed} className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Мне нужно было установить значение в переменную useRef(), которая была получена асинхронным http-запросом и сохранена в переменной useState(). Поэтому мне нужно было предоставить его как зависимость в функции useEffect():

          const [object, setObject] = useState('');

    const fetchObject = useCallback(async () => {
        const res = await fetch(apiUrl + "/object/", {});
        setObject({ ...await res.json() });
    }, [apiUrl]);

    const jsonEditor = React.createRef();

    useEffect(() => {
        fetchObject();
        if (jsonEditor.current && object.json) {
            jsonEditor.current.jsonEditor.set(JSON.parse(object.json));
        }
    }, [fetchObject, object.json]);

return (
    <div>
        <JsonEditor
            ref={jsonEditor}
            onChangeText={onChangeTextHandler}
        />
    </div>);
Другие вопросы по тегам