Chakra UIでファイル選択画面をカスタマイズ!Reactで簡単実装ガイド
はじめに
この記事では、ReactとChakra UIを使って、直感的で洗練されたファイルアップロードUIを作る方法を解説します。特に、ファイル選択を標準の<input>
タグではなく、Chakra UIのButtonコンポーネントを利用してカスタマイズする方法を紹介します。
目次
1. 背景と目的
デフォルトのファイル選択UIはシンプルですが、デザイン性に欠けることが多いです。Chakra UIのv2ではInputコンポーネントでファイル選択に関するUI設定が見当たらないため、オリジナルでChakra UIを利用しカスタマイズする方法を説明します。
2. 使用する技術とライブラリ
使用する技術はリンク先記事と同様です。
3. 実装手順
3.1 ベースコードの確認
ベースコードとしてリンク先記事のApp.tsxを利用します。
ベースコードApp.tsx
import React, { useState } from 'react';
import { Card, CardHeader, CardFooter, Heading, Flex, Button } from '@chakra-ui/react';
import axios from 'axios';
function App() {
const [file, setFile] = useState<File | null>(null);
const API_BASE_URL = 'http://localhost:8000';
const selectFile = async (e: React.ChangeEvent<HTMLInputElement>) => {
let zipData = e.target.files
if (zipData && zipData[0]) {
setFile(zipData[0])
}
}
const fileUpload = () => {
if(file) {
const formData = new FormData();
formData.append('file', file);
axios({
method: 'POST',
headers: { 'Content-Type': 'multipart/form-data' },
url: API_BASE_URL+'/upload',
data: formData,
withCredentials: true
})
.then(response => {
console.log(response.data)
})
.catch(err => {
console.log(err)
})
}
}
return (
<Flex justify='center' align='center' h='100vh'>
<Card align='center'>
<CardHeader>
<Heading size='md'>ファイルアップロード</Heading>
</CardHeader>
<CardFooter>
<input type='file' accept='application/zip' onChange={selectFile}/>
<Button colorScheme='blue' onClick={fileUpload}>アップロード</Button>
</CardFooter>
</Card>
</Flex>
);
}
export default App;
3.2 <input>
タグの非表示化
Chakra UIを利用するために標準の<input>
タグは非表示にするために<input>タグにstyle属性を追加を行います。
ここで<input>タグにそのままstyle=”display:none”を記載すると以下のエラーメッセージでエラーとなります。
Type 'string' has no properties in common with type 'Properties<string | number, string & {}>'.ts(2559)
index.d.ts(1999, 9): The expected type comes from property 'style' which is declared here
on type 'DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>'
これはCSSスタイルオブジェクトはReact.CSSPropertiesで定義する必要があるためです。
下記のように定義を行います。
const inputStyle: CSSProperties = {
display: 'none'
}
定義したReact.CSSPropertiesを<input>タグに適用すると下記のように変更出来ます。
<input type='file' style={{ ...inputStyle, display: 'none'}} accept='application/zip' onChange={selectFile}/>
3.3 useRef
でファイル選択を制御
ここではファイル選択時のイベントを制御します。
そのために<input>タグにReactのuseRefを利用しref属性を追加します。
const inputRef = useRef<HTMLInputElement>(null);
<input type='file' style={{ ...inputStyle, display: 'none'}} accept='application/zip' onChange={selectFile} ref={inputRef}/>
非表示にしている<input>タグのクリックをButtonコンポーネントで制御できるように以下のようコードを追加していきます。
const select = () => {
inputRef.current?.click();
console.log(inputRef.current?.value);
}
------------
<Button colorScheme='blue' onClick={select}>ファイル選択</Button>
これにより非表示となっている<input>タグによるファイル選択をChakra UIのボタンコンポーネントのクリックによるトリガーできるようになりました。
4. 変更前後のコード比較
最終的な変更後のコードは以下となります。
import React, { useState, useRef, useEffect, CSSProperties } from 'react';
import { Card, CardHeader, CardFooter, Heading, Flex, Button } from '@chakra-ui/react';
import axios from 'axios';
function App() {
const [file, setFile] = useState<File | null>(null);
const inputRef = useRef<HTMLInputElement>(null);
const API_BASE_URL = 'http://localhost:8000';
const inputStyle: CSSProperties = {
display: 'none'
}
const selectFile = async (e: React.ChangeEvent<HTMLInputElement>) => {
let zipData = e.target.files
if (zipData && zipData[0]) {
setFile(zipData[0])
}
}
const select = () => {
inputRef.current?.click();
console.log(inputRef.current?.value);
}
const fileUpload = () => {
if(file) {
const formData = new FormData();
formData.append('file', file);
axios({
method: 'POST',
headers: { 'Content-Type': 'multipart/form-data' },
url: API_BASE_URL+'/upload',
data: formData,
withCredentials: true
})
.then(response => {
console.log(response.data)
})
.catch(err => {
console.log(err)
})
}
}
return (
<Flex justify='center' align='center' h='100vh'>
<Card align='center'>
<CardHeader>
<Heading size='md'>ファイルアップロード</Heading>
</CardHeader>
<CardFooter>
<input type='file' style={{ ...inputStyle, display: 'none'}} accept='application/zip' onChange={selectFile} ref={inputRef}/>
<Button colorScheme='blue' onClick={select}>ファイル選択</Button>
<Button colorScheme='blue' onClick={fileUpload}>アップロード</Button>
</CardFooter>
</Card>
</Flex>
);
}
export default App;
UIを確認してみるとファイル選択をChakra UIのボタンコンポーネントによって行えるようになっていることが確認できました。
5. おわりに
今回の記事では、ReactとChakra UIを使ったファイルアップロードUIのカスタマイズ方法を解説しました。これにより、より使いやすく、デザイン性の高いUIを実現できます。Chakra UIを活用して、さらに洗練されたアプリを作ってみましょう!