React報錯之Cannot assign to ‘current’ because it is a read-only property
- 2022 年 8 月 11 日
- 筆記
正文從這開始~
總覽
當我們用一個null
值初始化一個ref
,但在其類型中不包括null
時,就會發生”Cannot assign to ‘current’ because it is a read-only property”錯誤。為了解決該錯誤,請在ref
的類型中包含null
。比如說,const ref = useRef<string | null>(null)
。
這裡有個例子來展示錯誤是如何發生的。
// App.tsx
import {useEffect, useRef} from 'react';
const App = () => {
const ref = useRef<string>(null);
useEffect(() => {
// ⛔️ Error: Cannot assign to 'current' because it is a read-only property.ts(2540)
ref.current = 'hello';
}, []);
return (
<div>
<h2>hello world</h2>
</div>
);
};
export default App;
上面例子的問題在於,當我們將null
作為初始值傳遞到useRef
鉤子中時,並且我們傳遞給鉤子的泛型中沒有包括null
類型,我們創建了一個不可變的ref
對象。
正確的泛型
為了解決該錯誤,我們必須在傳遞給鉤子的泛型中包括null
類型。
// App.tsx
import {useEffect, useRef} from 'react';
const App = () => {
// 👇️ include null in the ref's type
const ref = useRef<string | null>(null);
useEffect(() => {
ref.current = 'hello';
}, []);
return (
<div>
<h2>hello world</h2>
</div>
);
};
export default App;
在ref
的類型中,我們使用聯合類型來包括null
類型,這使它成為可變ref
對象。
現在這個例子中
ref
的類型是字元串或null
,它的current
屬性可以賦值為這兩種類型中的任意一種的值。
DOM元素
如果你的引用指向一個DOM元素,情況也是一樣的。如果你需要改變ref
的current
屬性的值,你必須將鉤子的類型定為 const ref = useRef<HTMLElement | null>(null)
。
注意,如果你不直接賦值給它的current
屬性,你不必在 ref
的類型中包含 null
。
// App.tsx
import {useEffect, useRef} from 'react';
const App = () => {
const ref = useRef<HTMLInputElement>(null);
useEffect(() => {
ref.current?.focus();
}, []);
return (
<div>
<input ref={ref} type="text" defaultValue="" />
</div>
);
};
export default App;
上述例子中的ref
是用來聚焦input
元素的。因為沒有對其.current
屬性進行賦值,所以沒有必要在其類型中包含null
。