The text starts here~
type guard
Use type guards to resolve the useRef
hook "Object is possibly null" error in React. For example, if (inputRef.current) {}
. Once null
is excluded from the type of ref
, we are able to access the properties on ref
.
Below is an example of how an error can occur.
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>
);
}
The problem in the snippet is that TypeScript can't ensure that we assign an element or a value to a ref, so its current
property could be null
.
To fix this error, we have to use a type guard to exclude null
from its type before accessing properties on the ref type.
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>
);
}
We use a simple if
statement as a type guard to ensure that the ref
current
property on ---9e858ab876b6c785b9ab47cecb83527e--- does not store null
. When the program enters the if
block, TypeScript will know that the ---8521b27e464ef25d7ca3fea5aa906bdaa--- property on the current
ref
will not store the null
---property.
Make sure to use generics on the useRef hook, correct type declarationref
current
.
Note that we passed a generic to ref
the value type of ---f217f0c193605fdc93ce6ed38793b0d2--- as HTMLInputElement
.
一些常用的类型有: HTMLInputElement
, HTMLButtonElement
, HTMLAnchorElement
, HTMLImageElement
, HTMLTextAreaElement
, HTMLSelectElement
Wait.
If you store a different value in ref
, make sure to pass a specific type to the generic type of the useRef
hook, e.g. const ref = useRef<{name: string}>(null);
.
If the ref
current
attribute on ---79b39c20e98a37ba169075c44bbc47db--- stores null
, we can also use the optional chain ?.
to short-circuit the operation.
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>
);
}
If the reference is null ( null
or undefined
), the optional chaining ?. operator will short-circuit without throwing an error.换句话说, ref
上的current
null
,操作符会短路运算从而返回undefined
。 instead of trying to call the undefined
focus
method on ---a121fed99a9f6eb64ab4758b8e226146---, resulting in a runtime error.
non-null assertion
Another solution is to use the non-null assert !
operator.
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>
);
}
In TypeScript, the exclamation mark is called the non-null assertion operator. Used to remove null
and undefined
from a type without any explicit type checking.
When we use a non-null assertion, we are basically telling TS that the ref
current
attribute on the object will not be stored null
or undefined
.
Note that this approach is not type-safe, as TypeScript does not perform any checks to ensure the property is not null.
Summarize
The "Object is possibly null" error is caused because useRef()
the hook can pass an initial value as a parameter, and we pass null
as the initial value. The hook returns a mutable ref
object whose .current
property is initialized to the passed parameter.
When passing the ref prop to an element, such as <input ref={myRef} />
, React will set the ref
object's .current
property to the corresponding DOM node, but TypeScript can't tell if our will set ref
as a DOM element, or set its value later in our code.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。