简体   繁体   English

React Hooks:为什么是.current null for useRef Hook?

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

I have a simple example of a component:我有一个简单的组件示例:

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);

I would expect that observed.current would be of type element and current would not be empty but the div element with all its properties.我希望observed.current是element 类型,current 不是空的,而是div 元素及其所有属性。 My understanding would be:我的理解是:

  1. The ref is initialised with a value of null ref 被初始化为 null
  2. Null is overwritten by the ref Null 被 ref 覆盖

But as it turns out, .current remains empty.但事实证明, .current仍然是空的。 This is bad since I want to pass observed to a function that expects an argument of type Element.这很糟糕,因为我想将观察传递给需要元素类型参数的 function。

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

Ref.current is null because the ref is not set till after the function returns and the content is rendered. Ref.current为空,因为直到函数返回并呈现内容之后才会设置 ref。 The useEffect hook fires every time the value of contents of the array passed to it changes.每次传递给它的数组内容的值发生变化时, useEffect钩子都会触发。 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.通过将observed数组中,并通过传递一个回调日志observed到控制台中,useEffect钩子可以被利用来完成你的任务。

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

Edit: This only works on the first render as changes to a ref do not trigger re-renders.编辑:这仅适用于第一次渲染,因为对 ref 的更改不会触发重新渲染。 But the general statement about useEffect still holds.但是关于 useEffect 的一般说法仍然成立。 If you want to observe changes to a ref of a dom element, you can use a callback as ref.如果你想观察一个 dom 元素的 ref 的变化,你可以使用回调作为 ref。

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

Code Sandbox代码沙盒

At the time the console.log happens, the ref isn't yet set.console.log发生时, ref尚未设置。 Try putting your console.log into a useEffect hook and it works as you want it to.尝试将您的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);

This is what I ended up doing since calling useEffect on rlvRef did not capture all events.这就是我最终做的事情,因为在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); }}
    ... 
  />
)

I needed to set a value into the useRef()-variable which was retrieved by an async http-request and was saved in a useState()-variable.我需要在 useRef() 变量中设置一个值,该变量由异步 http 请求检索并保存在 useState() 变量中。 So i needed to provide it as an dependency as well in the useEffect()-function:所以我需要在 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>);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM