目錄
useRef是甚麼
useRef是一個hook,其current
屬性可以存任何值(mutable
),且不會觸發re-render
常
被用來存DOM element
的ref
The useRef() Hook isn’t just for DOM refs. The “ref” object is a generic container whose current property is mutable and can hold any value, similar to an instance property on a class.
用法 - 存DOM
這邊舉存DOM的情況為例
假設有兩個組件FileUpload和ImageCrop,它們的關係是平行的
有個2需求
1.FileInput的上傳區域UI要自己刻,不要用原生的input
2.在ImageCrop內的clear button被按時要清空FileUpload的input的值
也就是說FileUpload和ImageCrop都會操作到input
這有三個方式可以處理
- 直接把FileUpload和ImageUpload塞成一個組件
- 用
render props
的方式把回傳ImageUpload的函式傳入FileUpload - 把const inputRef = useRef(null)拉到這兩個組件的父組件裡,然後把inputRef用props
因為1不利於復用,3的話把inputRef放在父組件不太合理,所以以下使用第2種方式
// FileUpload
interface FileUploadProps {
renderChildren: (inputEle: HTMLInputElement) => ReactNode;
onFileSelect: (e: ChangeEvent<HTMLInputElement>) => void;
}
const FileUpload: FunctionComponent<FileUploadProps> = ({
renderChildren,
onFileSelect
}) => {
const inputRef = useRef<HTMLInputElement | null>(null);
return (
<>
<div
style={{
display: "flex",
justifyContent: "space-around",
alignItems: "center",
borderRadius: 4,
border: "1px dashed #cccccc",
padding: 12
}}
>
<h3>select photo you want to upload</h3>
<button
onClick={() => {
inputRef.current?.click();
}}
>
select
</button>
</div>
<input
type="file"
ref={inputRef}
onChange={onFileSelect}
style={{
display: "none"
}}
/>
<p>{inputRef.current !== null}</p>
<div style={{ margin: "16px" }}>{renderChildren(inputRef.current)}</div>
</>
);
};
// ImageCrop
interface ImageCropProps {
handlePhotoClear: () => void;
previewSrc: string;
}
const ImageCrop: FunctionComponent<ImageCropProps> = ({
handlePhotoClear,
previewSrc
}) => {
return (
<div>
<img src={previewSrc} alt="" style={{ width: "100%" }} />
{previewSrc && (
<>
<button
type="button"
onClick={() => {
handlePhotoClear();
}}
>
clear
</button>
<button type="button" style={{ marginLeft: 16 }}>
ok
</button>
</>
)}
</div>
);
};
用起來會長這樣
<ImageCrop
previewSrc={previewSrc}
handlePhotoClear={() => {
setPreviewSrc("");
inputEle.value = "";
}}
/>
用法 - 存值
useRef的另一個用法useState類似,但它可以確保
S值的reference永遠是同一個
另外current被更新時
,組件也不會重新渲染組件
在codesandbox - useRef中使用了useState與useRef
你會發現只有useState的set function被呼叫時顏色才會變
而顏色變是因為每次re-render class name就會改變