Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use useRef with TypeScript #44

Open
jtwang7 opened this issue Mar 17, 2022 · 0 comments
Open

How to use useRef with TypeScript #44

jtwang7 opened this issue Mar 17, 2022 · 0 comments

Comments

@jtwang7
Copy link
Owner

jtwang7 commented Mar 17, 2022

How to use useRef with TypeScript

参考文章:


To use useRef with TypeScript, it is actually pretty easy, all you need to do is provide the type that you want to the function via open and closed chevrons like you would with other React hooks:

function useRef<T>(initialValue: T): MutableRefObject<T>;
interface MutableRefObject<T> {
  current: T = undefined;
}

useRef()定义如上,在使用时我们只需要在<>处传入对应的泛型类型即可。

useRef()包裹变量

import React, { useRef } from "react"

export default function ExampleComponent() {
  const countRenders = useRef<number>(0)

  countRenders.current += 1

  return <p>Current renders: {countRenders.current}</p>
}

包裹变量时,我们只需要保证泛型T与(初始值|存入值)类型匹配即可。

useRef()包裹Element

export default function ExampleComponent() {
  const paraRef = useRef<null | HTMLParagraphElement>(null)

  return <p ref={paraRef}>Current renders: {countRenders.current}</p>
}

本例在useRef<T>()中传入了 type null | HTMLParagraphElement,指明当前 useRef可以是 types nullHTMLParagraphElement两者之一。

  • 指定HTMLParagraphElement是因为我们最终存储的<p>标签属于HTMLElement元素类型,具体类型为HTMLParagraphElement,可在vscode中将鼠标悬浮到对应的标签元素上查看提示。
  • 此外,我们还需要指定null类型,这是因为ref对象不会直接初始化为<p>标签,真正赋值为对应标签元素的时刻发生在第一次渲染render完成后。假如不指定null,程序将在编译阶段就报错。
const paraRef = useRef<HTMLParagraphElement>(null!)

除了使用 联合类型 来避免初始化为null时导致的编译报错外,我们还可以使用!非空断言,它的作用就是将nullundefined排除在检查范围之外。

关于MutableRefObject

MutableRefObject: useRef返回的ref对象所对应的类型。

interface MutableRefObject<T> {
  current: T = undefined;
}

一个空的 MutableRefObject 对应的类型接口 { current: undefined },具体返回的类型由泛型T指定。

❗️**值得一提的是:**在使用useRef()时,尽量初始化null值,尽管它默认会填写为undefined,但大多数情况下,采用默认值会导致意外的错误。

export default function ExampleComponent() {
  // useRef初始化为null
  const paraRef = useRef<null | HTMLParagraphElement>(null)
  return <p ref={paraRef}>Current renders: {countRenders.current}</p>
}

上述例子中,useRef若采用默认赋值undefined会报错,因为html元素ref对象不接受一个未定义的值作为其实例值。

How to fix the “object is possibly ‘null’” error in useRef with TypeScript.

export default function ExampleComponent() {
  const paraRef = useRef<null | HTMLParagraphElement>(null)

  useEffect(() => {
    console.log(paraRef.current.innerHTML) // "object is possibly 'null'"
  })

  return <p ref={paraRef}>Current renders: {countRenders.current}</p>
}

由于我们通常会设置useRef的初始值为null,尽管有时候我们知道在运行的某个阶段ref.current不可能取到null值,但是程序仍会在编译阶段报错。

上例中,尽管运行到useEffect时,<p>标签对应的ref对象已经赋值给了paraRef对象,paraRef.current !== null,但是会编译报错。

解决方案一!非空断言

解决方案二?.可选链操作符

export default function ExampleComponent() {
  const paraRef = useRef<null | HTMLParagraphElement>(null)

  useEffect(() => {
    console.log(paraRef.current?.innerHTML) // Hello World
  })

  return <p ref={paraRef}>Hello World</p>
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant