React報(bào)錯之Object?is?possibly?null的問題及解決方法
類型守衛(wèi)
使用類型守衛(wèi)來解決React中useRef鉤子“Object is possibly null”的錯誤。比如說,if (inputRef.current) {} 。一旦null被排除在ref的類型之外,我們就能夠訪問ref上的屬性。

下面是一個錯誤如何發(fā)生的示例。
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類型上的屬性之前,我們必須使用類型守衛(wèi)來從其類型中排除null。
import {useEffect, useRef} from 'react';
export default function App() {
const inputRef = useRef<HTMLInputElement>(null);
useEffect(() => {
// ??? ref could be null here
if (inputRef.current != null) {
// ??? TypeScript knows that ref is not null here
inputRef.current.focus();
}
}, []);
return (
<div>
<input ref={inputRef} type="text" id="message" />
<button>Click</button>
</div>
);
}
我們使用簡單的if語句作為類型守衛(wèi),來確保ref上的current屬性不存儲null。當(dāng)程序進(jìn)入到if代碼塊中,TypeScript就會知道ref對象上的current屬性就不會存儲null。
確保在useRef鉤子上使用泛型,正確的類型聲明ref上的current屬性。
注意,我們傳遞了一個泛型來將ref的值類型聲明為HTMLInputElement。
一些常用的類型有:HTMLInputElement,HTMLButtonElement,HTMLAnchorElement,HTMLImageElement,HTMLTextAreaElement,HTMLSelectElement 等等。
如果你在ref中存儲了不同的值,請確保將特定類型傳遞給useRef鉤子的泛型,例如const ref = useRef<{name: string}>(null); 。
如果ref上的current屬性存儲了null,我們也可以使用可選鏈?. 操作符進(jìn)行短路運(yùn)算。
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>
);
}
如果引用是空值(null或者undefined),可選鏈?.操作符會進(jìn)行短路運(yùn)算,而不會拋出錯誤。換句話說,如果ref上的current屬性存儲了null,操作符會短路運(yùn)算從而返回undefined。而不會在undefined上嘗試調(diào)用focus方法,導(dǎo)致一個運(yùn)行時錯誤。
非空斷言
另一種解決方案是使用非空斷言!操作符。
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中,感嘆號標(biāo)記被稱為非空斷言操作符。被用來從類型中移除null和undefined ,而不用進(jìn)行任何顯式的類型檢查。
當(dāng)我們使用非空斷言時,基本上我們就是在告訴TS,ref對象上的current屬性不會存儲null或者undefined。
請注意,這種方法不是類型安全的,因?yàn)門ypeScript不執(zhí)行任何檢查以確保屬性不是空的。
總結(jié)
造成 "Object is possibly null"的錯誤是因?yàn)?code>useRef()鉤子可以傳遞一個初始值作為參數(shù),而我們傳遞null作為初始值。該鉤子返回一個可變的ref對象,其.current屬性被初始化為所傳遞的參數(shù)。
當(dāng)傳遞ref prop給一個元素時,比如<input ref={myRef} /> ,React將ref對象的.current屬性設(shè)置為相應(yīng)的DOM節(jié)點(diǎn),但TypeScript無法確定我們是否會將ref設(shè)置為DOM元素,或在我們的代碼中稍后設(shè)置其值。
到此這篇關(guān)于React報(bào)錯之Object is possibly null的文章就介紹到這了,更多相關(guān)React Object is possibly null報(bào)錯內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React通過ref獲取子組件的數(shù)據(jù)和方法
這篇文章主要介紹了React如何通過ref獲取子組件的數(shù)據(jù)和方法,文中有詳細(xì)的總結(jié)內(nèi)容和代碼示例,具有一定的參考價(jià)值,需要的朋友可以參考下2023-10-10
React-Native做一個文本輸入框組件的實(shí)現(xiàn)代碼
這篇文章主要介紹了React-Native做一個文本輸入框組件的實(shí)現(xiàn)代碼,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-08-08
React Native之prop-types進(jìn)行屬性確認(rèn)詳解
本篇文章主要介紹了React Native之prop-types進(jìn)行屬性確認(rèn)詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-12-12
react+antd.3x實(shí)現(xiàn)ip輸入框
這篇文章主要為大家詳細(xì)介紹了react+antd.3x實(shí)現(xiàn)ip輸入框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10
React組件對子組件children進(jìn)行加強(qiáng)的方法
這篇文章主要給大家介紹了關(guān)于React組件中對子組件children進(jìn)行加強(qiáng)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用React具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06
React函數(shù)組件傳參的實(shí)現(xiàn)
React函數(shù)組件通過接受props實(shí)現(xiàn)組件間的數(shù)據(jù)傳遞,通過組件標(biāo)簽的屬性向子組件傳遞數(shù)據(jù),并在子組件中通過參數(shù)接收,還可以使用ES6的解構(gòu)賦值,函數(shù)也能作為props傳遞,以實(shí)現(xiàn)父子組件間的交互和通信,下面就來具體了解一下2024-09-09
react router 4.0以上的路由應(yīng)用詳解
本篇文章主要介紹了react router 4.0以上的路由應(yīng)用詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-09-09

