React Hooks: Why is .current null for useRef Hook?

后端 未结 3 551
温柔的废话
温柔的废话 2020-12-24 11:41

I have a simple example of a component:

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

  return (
    
相关标签:
3条回答
  • 2020-12-24 11:50

    At the time the console.log happens, the ref isn't yet set. Try putting your console.log into a useEffect hook and it works as you want it to.

    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);
    
    0 讨论(0)
  • 2020-12-24 11:55

    Ref.current is null because the ref is not set till after the function returns and the content is rendered. The useEffect hook fires every time the value of contents of the array passed to it changes. By passing observed in the array and by passing a callback that logs observed to the console, the useEffect hook can be leveraged to accomplish your task.

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

    Edit: This only works on the first render as changes to a ref do not trigger re-renders. But the general statement about useEffect still holds. If you want to observe changes to a ref of a dom element, you can use a callback as ref.

      <div 
        ref={el => { console.log(el); observed.current = el; }} // or setState(el)
        className="App"
      >
    

    Code Sandbox

    0 讨论(0)
  • 2020-12-24 11:59

    This is what I ended up doing since calling useEffect on rlvRef did not capture all events.

    const rlvRef = useRef()
    const [refVisible, setRefVisible] = useState(false)
    
    useEffect(() => {
      if (!refVisible) { 
        return
      }
      // detected rendering
    }, refVisible)
    
    return (
    <RecyclerListView
                  ref={el => { rlvRef.current = el; setRefVisible(!!el); }}
    ... />
    )
    
    0 讨论(0)
提交回复
热议问题