📂
[React]ファイル選択した画像を表示する(TypeScript)
はじめに
プロフィール画像を選択する時など、ローカルにある画像をReactで表示する際のやり方がわからなかったのでメモ
基本編: ファイル選択した画像を表示する
やり方
-
<input type="file" />
でファイルを選択する -
window.URL.createObjectURL()
でオブジェクトURLを生成する -
useState()
で<img src={xxx}>
を更新する
実際のコード
input
のonChange
でイベントを発火し、
選択されたファイルをwindow.URL.createObjectURL()
に渡しています
※スタイルにはTailWind CSSを使用していますが、処理内容には影響しないため省略します
App.tsx
import React, { useState } from 'react';
import './App.css';
function App() {
// useState()で画像のパスを保持
// ※デフォルトで表示する画像を初期値で指定(この例ではpublicフォルダのdefault-profile.pngを指定)
const [profileImage, setProfileImage] = useState('default-profile.png');
const onFileInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (!e.target.files) return;
// React.ChangeEvent<HTMLInputElement>よりファイルを取得
const fileObject = e.target.files[0];
// オブジェクトURLを生成し、useState()を更新
setProfileImage(window.URL.createObjectURL(fileObject));
};
return (
<div className="flex justify-center items-center mt-8">
<img src={profileImage} className="h-32 w-32 rounded-full" />
<input type="file" accept="image/*" onChange={onFileInputChange} className="pl-4" />
</div>
);
}
export default App;
実行結果
応用編: インプットボタンをカスタマイズする
デフォルトの「選択...」の部分をカスタマイズしていきます
やり方
-
useRef()
で<input />
への参照を定義する - ボタンクリック時に、
<input />の参照.current.click()
でファイル選択のイベントを呼び出す -
<input />
のonChange()
の中でuseState()
を更新する
カスタマイズ用のコード
useRef<HTMLInputElement>(null!);
でinput属性への参照を定義し、
元々あった<input />
はhidden
属性で隠しています
代わりに、ボタンクリック時にinputRef.current.click();
でファイル選択のイベントを発火させています
App.tsx
import React, { useRef, useState } from 'react';
import './App.css';
function App() {
const [profileImage, setProfileImage] = useState('default-profile.png');
const inputRef = useRef<HTMLInputElement>(null!); // 追加
// 追加
const onProfileButtonClick = () => {
// useRef<HTMLInputElement>のcurrent要素を呼び出し、ファイル選択画面を表示
inputRef.current.click();
};
const onFileInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (!e.target.files) return;
const fileObject = e.target.files[0];
setProfileImage(window.URL.createObjectURL(fileObject));
};
return (
<div className="flex justify-center items-center mt-8">
<img src={profileImage} className="h-32 w-32 rounded-full" />
{/* ref属性を指定し、hiddenで要素を隠す */}
<input hidden ref={inputRef} type="file" accept="image/*" onChange={onFileInputChange} />
{/* ファイル選択用のボタンを用意 */}
<button
className="bg-blue-500 text-white px-4 py-2 rounded-md ml-4"
onClick={onProfileButtonClick}
>
プロフィール画像を選択
</button>
</div>
);
}
export default App;
実行結果
参考
Discussion