🐕
【React+Material UI】画像アップロード機能実装方法
概要
画像をアップロードする機能の実装方法について説明します。
サンプルコード
下記がサンプルコードになります。
まず、画像アップロードボタンを定義します。
仕組みは下記のようになっています。
・<input>
をcssで見えないようにする。
・<label>
のhtmlFor
で<input>
と紐づけをする。
上記の結果、疑似的にボタンを押すとファイル選択画面が表示されるという仕組みになっています。
const useUploadButtonStyles = makeStyles((theme) =>
createStyles({
input: {
display: 'none',
},
})
);
export const UploadButton = (props) => {
const classes = useUploadButtonStyles();
return (
<label htmlFor={`upload-button-${props.name}`}>
<input
accept="image/*"
className={classes.input}
id={`upload-button-${props.name}`}
name={props.name}
multiple
type="file"
onChange={props.onChange}
/>
<Button variant="contained" component="span" {...props}>
{props.children}
</Button>
</label>
);
};
<input>
をcssで見えないようにする。
input: {
display: 'none',
},
css
でdisplay:'none'
にすることで画面から表示されないようになります。
<label>
のhtmlFor
で<input>
と紐づけをする。
<label htmlFor={`upload-button-${props.name}`}>
<input
accept="image/*"
className={classes.input}
id={`upload-button-${props.name}`}
name={props.name}
multiple
type="file"
onChange={props.onChange}
/>
<Button variant="contained" component="span" {...props}>
{props.children}
</Button>
</label>
<label>
のhtmlFor
と<input>
のid
が同じになるように設定するのがポイントです。
こうすることでボタンが押される(≒labelが押される)ファイル選択画面が表示されるようになります。
使い方
const Example = () => {
const [postFileData, setPostFileData] = useState({})
const changeUploadFile = async (event) => {
const { name, files } = event.target;
setPostFileData({
...postFileData,
[name]: files[0],
});
event.target.value = '';
};
return (
<UploadButton
className="primary"
name="image"
onChange={changeUploadFile}
>
アップロード
</UploadButton>
)
}
上記が実際のアップロードボタンのコードになります。
ファイルがアップロードされるとchangeUploadFile
が発火します。
changeUploadFile
の処理内容について説明します。
file[0]
にアップロードされた画像が入っています。
下記の行がないと同じファイル名のファイルをアップロードした時にonChange
イベントが発火されません。下記の行を追加することで同じファイル名のファイルをアップロードしても再度値をセットしなおされるようになります。
event.target.value = '';
送信方法
送信にはFormData
を使います。append
メソッドを使ってファイルを詰めてaxiosで送信します。
const formData = new FormData();
postData.append(
'image',
postFileData.image ? postFileData.image : ''
);
const response = axios.post('/image/store', params, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
更新の場合の注意点
更新の場合は注意が必要です。PUTメソッドで送ろうとするとこれはできません。
const response = axios.put('/image/update', params, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
下記のようにしないと送ることができません。注意してください。
postData.append('_method', 'PUT');
const response = axios.post('/image/update', params, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
以上です。読んでいただきありがとうございました。
誤字、脱字、間違い等ありましたらコメント頂ければ幸いです。
Discussion