React Hooks:为啥 useRef Hook 的 .current 为空?
Posted
技术标签:
【中文标题】React Hooks:为啥 useRef Hook 的 .current 为空?【英文标题】:React Hooks: Why is .current null for useRef Hook?React Hooks:为什么 useRef Hook 的 .current 为空? 【发布时间】:2019-10-25 17:40:52 【问题描述】:我有一个简单的组件示例:
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
的类型为 element 并且 current 不会为空,而是 div 元素及其所有属性。我的理解是:
-
ref 被初始化为 null 值
Null 被 ref 覆盖
但事实证明,.current
仍然是空的。这很糟糕,因为我想将观察到的参数传递给需要元素类型参数的函数。
https://codesandbox.io/embed/purple-forest-0460k
【问题讨论】:
【参考方案1】:Ref.current
为 null,因为直到函数返回并呈现内容后才会设置 ref。每次传递给它的数组内容的值发生变化时,useEffect 钩子都会触发。通过在数组中传递 observed
并将记录 observed
的回调传递到控制台,可以利用 useEffect 挂钩来完成您的任务。
useEffect(() =>
console.log(observed.current);
, [observed]);
编辑:这仅适用于第一次渲染,因为对 ref 的更改不会触发重新渲染。但是关于 useEffect 的一般说法仍然成立。如果要观察 dom 元素的 ref 的变化,可以使用 callback as ref.
<div
ref=el => console.log(el); observed.current = el; // or setState(el)
className="App"
>
Code Sandbox
【讨论】:
非常感谢!我对 Hooks 非常了解,但对于功能组件,我会假设整个功能是“渲染功能”。您是否可以参考我在渲染函数中可以做和不能做的事情? “你必须检查useEffect
钩子中的值” - 这句话严格来说不正确,我可以记住可以访问 ref 的回调函数。要点是 ref 为 null 因为 UI 尚未真正呈现,useEffect
在这里工作,因为 useEffect
它等同于 componentDidMount
和其他一些运行 after 的钩子组件已渲染。
@Jame 更改了文本,对未来的读者来说应该更清楚。 reactjs.org/docs/hooks-reference.html#usememo
@AvinKavish 编辑看起来好多了 IMO :) Xen_mar 查看useCallback
我认为 useEffect 只会运行一次,因为即使观察到的电流发生变化,观察到的也永远不会改变。这就是 useRef 的意义所在。 “返回的对象将在组件的整个生命周期内持续存在。” codesandbox.io/s/romantic-tharp-dsnpx【参考方案2】:
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);
【讨论】:
【参考方案3】:这是我最终做的,因为在 rlvRef
上调用 useEffect
并没有捕获所有事件。
const rlvRef = useRef()
const [refVisible, setRefVisible] = useState(false)
useEffect(() =>
if (!refVisible)
return
// detected rendering
, refVisible)
return (
<RecyclerListView
ref=el => rlvRef.current = el; setRefVisible(!!el);
...
/>
)
【讨论】:
就像一个魅力。其他答案都不适合我。 不能分配给'current',因为它是一个只读属性以上是关于React Hooks:为啥 useRef Hook 的 .current 为空?的主要内容,如果未能解决你的问题,请参考以下文章
react hooks 之 useRef, useImperativeHandle
在 React-Hooks UseRef 我无法获得新的状态值
ZF_react hooks useEffect的实现 useRef useImperativeHandle的实现,react整体功能实现完毕