网站首页 > 基础教程 正文
使用类型保护来解决 React 中的 useRef 钩子的“Object is possibly null”错误,例如 if(inputRef.current){}。 一旦 null 从 ref 的类型中排除,我们就可以访问 ref 上与其类型相对应的属性。
下面是产生该错误发生示例代码。
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 应该能够帮助你自动完成。
一些常用的类型有:HTMLInputElement、HTMLButtonElement、HTMLAnchorElement、HTMLImageElement、HTMLTextAreaElement、HTMLDivElement 等。
如果你在 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 元素还是稍后在我们的代码中设置它的值 。
猜你喜欢
- 2024-11-24 React源码分析与实现(一):组件的初始化与渲染「实践篇」
- 2024-11-24 React 最简单的入门应用项目
- 2024-11-24 「干货」深入浅出React组件逻辑复用的那些事儿
- 2024-11-24 「干货满满」React Hooks 最佳实践
- 2024-11-24 React开发必须知道的34个技巧
- 2024-11-24 React组件应该如何封装?
- 2024-11-24 React.js前端框架初学技术总结
- 2024-11-24 前端架构师成长之路:5 分分钟搞懂面试官必问 React 题
- 2024-11-24 只会Vue的我,用两天学会了react,这个方法您也可以
- 2024-11-24 react高质量笔记_9(Diffing算法)
- 最近发表
- 标签列表
-
- gitpush (61)
- pythonif (68)
- location.href (57)
- tail-f (57)
- pythonifelse (59)
- deletesql (62)
- c++模板 (62)
- css3动画 (57)
- c#event (59)
- linuxgzip (68)
- 字符串连接 (73)
- nginx配置文件详解 (61)
- html标签 (69)
- c++初始化列表 (64)
- exec命令 (59)
- canvasfilltext (58)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- node教程 (59)
- console.table (62)
- c++time_t (58)
- phpcookie (58)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)