专业编程基础技术教程

网站首页 > 基础教程 正文

React userRef 错误 Object is possibly null 修复

ccvgpt 2024-11-24 12:29:23 基础教程 4 ℃

使用类型保护来解决 React 中的 useRef 钩子的“Object is possibly null”错误,例如 if(inputRef.current){}。 一旦 null 从 ref 的类型中排除,我们就可以访问 ref 上与其类型相对应的属性。

下面是产生该错误发生示例代码。

React userRef 错误 Object is possibly null 修复

import {useEffect, useRef} from 'react';

export default function App() {
  const inputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    // ?? Object is possibly 'null'.ts(2531)
    inputRef.current.focus();
  }, []);

  return (
    <div>
      <input ref={inputRef} type="text" id="message" />
      <button>Click</button>
    </div>
  );
}

代码片段中的问题是 TypeScript 不能保证我们会将 ref 分配给一个元素或为其分配一个值,因此它的 current 属性可能为 null。

为了解决这个错误,我们必须在访问它的属性之前使用类型保护从 ref 的类型中排除 null。

import {useEffect, useRef} from 'react';

export default function App() {
  const inputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    // 这里 ref 可以是 null
    if (inputRef.current != null) {
      // TypeScript 知道这里的 ref 不为 null
      inputRef.current.focus();
    }
  }, []);

  return (
    <div>
      <input ref={inputRef} type="text" id="message" />
      <button>Click</button>
    </div>
  );
}

我们使用了一个简单的 if 语句作为类型保护,以确保 ref 上的当前属性不存储空值。

TypeScript 知道,一旦我们进入 if 块,ref 对象的当前属性就不会存储空值。

确保使用 useRef 钩子上的泛型来正确键入 ref 的当前属性

请注意,我们传递了一个泛型来将 ref 的值输入到 HTMLInputElement。

DOM 元素的类型统一命名为 HTML***Element。 一旦你开始输入 HTML..,你的 IDE 应该能够帮助你自动完成。

一些常用的类型有:HTMLInputElementHTMLButtonElementHTMLAnchorElementHTMLImageElementHTMLTextAreaElementHTMLDivElement 等。

如果你在 ref 中存储不同的值,请确保将特定类型传递给 useRef 钩子的泛型,例如·const ref = useRef<{name: string}>(null);

如果 ref 上的当前属性存储空值,我们也可以使用可选链接 (?.) 运算符来阻断运行。

import {useEffect, useRef} from 'react';

export default function App() {
  const inputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    // ? optional chaining (?.)
    inputRef.current?.focus();
  }, []);

  return (
    <div>
      <input ref={inputRef} type="text" id="message" />
      {/* Cannot find name 'button'.ts(2304) */}
      <button>Click</button>
    </div>
  );
}

如果 ref 为空(null 或 undefined),则可选链接 (?.) 运算符会阻断运行而不是引发错误。

换句话说,如果 ref 上的当前属性存储了一个 null 值,则操作符会短路返回 undefined,而不是尝试在 undefined 值上调用 focus() 方法并导致运行时错误。

在 React 中使用 refs 的“对象可能为空”错误的另一种解决方案是使用非空 (!) 断言运算符。

import {useEffect, useRef} from 'react';

export default function App() {
  const inputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    // ? using non-null (!) assertion
    inputRef.current!.focus();
  }, []);

  return (
    <div>
      <input ref={inputRef} type="text" id="message" />
      {/* Cannot find name 'button'.ts(2304) */}
      <button>Click</button>
    </div>
  );
}

感叹号在 TypeScript 中称为非空断言运算符。 它用于在不进行任何显式类型检查的情况下从类型中删除 null 和 undefined。

当我们使用它时,我们基本上告诉 TypeScript ref 对象上的当前属性不存储 null 或 undefined 的值。

请注意,这种方法不是类型安全的,因为 TypeScript 不执行任何检查以确保属性不为空。

导致“Object is possible null”错误的是因为 useRef() 钩子可以传递一个初始值作为参数,而我们将它传递给 null 作为初始值。

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

当我们将 ref prop 传递给元素时,例如 <input ref={myRef} />,React 将 ref 对象的 .current 属性设置为对应的 DOM 节点,但 TypeScript 无法确定我们是要设置 ref 为 DOM 元素还是稍后在我们的代码中设置它的值 。

Tags:

最近发表
标签列表