# React技巧之useRef钩子

原文链接:https://bobbyhadz.com/blog/react-update-state-when-props-change (opens new window)

作者:Borislav Hadzhiev (opens new window)

正文从这开始~

# 与document.querySelector等价

在React中,与document.querySelector() 方法等价的是使用refs。为了选择一个元素,在元素上设置ref属性,并设置为调用useRef()钩子的返回值。并使用ref上的current属性访问dom元素,例如ref.current

import {useRef, useEffect} from 'react';

export default function App() {
  const ref = useRef(null);

  useEffect(() => {
    // 👇️ use a ref (best)
    const el2 = ref.current;
    console.log(el2);

    // 👇️ use document.querySelector()
    // should only be used when you can't set a ref prop on the element
    // (you don't have access to the element)
    const el = document.querySelector('#container');
    console.log(el);
  }, []);

  return (
    <div>
      <div ref={ref} id="container">
        <h2>Some content here</h2>
      </div>
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

image.png

# useRef()钩子

useRef()钩子可以传递一个初始化值作为参数。该钩子返回一个可变的ref对象,其.current属性被初始化为传递的参数。

需要注意的是,我们必须访问ref对象的current属性,以获得对我们设置了ref属性的div元素的访问。

const el2 = ref.current;
console.log(el2);
1
2

当我们给元素传递ref属性时,比如说,<div ref={myRef} /> ,React将ref对象的.current属性设置为相应的DOM节点。

我们为useEffect钩子传递一个空的依赖数组,因此只有当组件挂载时才会运行。

useEffect(() => {
  const el2 = ref.current;
  console.log(el2);
}, []);
1
2
3
4

这里我们使用useEffect钩子,是因为我们想要确保ref已经被设置在了元素上,并且元素已经渲染成为DOM。

需要注意的是,当使用ref来访问元素的时候,你不必在元素上设置id属性。

这里有一个在React中使用ref的极简示例。

import {useRef, useEffect} from 'react';

export default function App() {
  const ref = useRef(null);

  useEffect(() => {
    const el2 = ref.current;
    console.log(el2);
  }, []);

  return (
    <div>
      <div ref={ref}>
        <h2>Some content here</h2>
      </div>
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# document.querySelector

如果你不能访问你试图在你的组件中选择的元素,并且不能简单地对其设置ref 属性,那么就使用document.querySelector方法。

import {useEffect} from 'react';

export default function App() {
  useEffect(() => {
    // 👇️ use a ref (best)
    const el = document.querySelector('#container');
    console.log(el);
  }, []);

  return (
    <div>
      <div id="container">
        <h2>Some content here</h2>
      </div>
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

你必须在useEffect钩子,或者某个事件发生时调用document.querySelector()方法。举个例子,你可以在onClick事件处理函数中安全的访问ref上的current属性,那是因为当事件被触发时,该元素将出现在DOM中。

# 总结

如果你试图通过 document.querySelectorref 直接在你的函数组件的render方法中访问一个元素,该元素可能还没有渲染。

useEffect钩子是在组件中的DOM元素被渲染到DOM后运行的,所以如果提供了id属性的元素存在,那么将会被选中。