เขียนโดย
Thanawat Udchachon
Internship @ borntoDev
เริ่มต้นการใช้งาน
เจ้าตัว react-dropzone เนี่ย มันก็เป็น React hook ง่าย ๆ ตัวหนึ่งที่ใช้สำหรับการทำส่วนของการลากวางไฟล์ และเช่นเคยสำหรับการจะใช้ library อะไร เราก็ต้องทำการติดตั้งกันก่อน ซึ่งก็สามารถทำได้ด้วยคำสั่ง npm install react-dropzone
ส่วนตัวโค้ด เพื่อเป็นการไม่เสียเวลา เราก็จะเริ่มจากโค้ดที่เราได้ทำไปกันตั้งแต่บทความก่อนหน้านะครับ
import React, { useState } from 'react';
import Axios from 'axios';
export default function Upload() {
Axios.defaults.withCredentials = true;
const [imageFile, setImageFile] = useState('');
const handleFileInputChange = (e) => {
const file = e.target.files[0];
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = () => {
setImageFile(reader.result);
}
}
const handleSubmitFile = (e) => {
e.preventDefault();
if (!previewSource) return;
Axios.put(`api url`, { data: imageFile});
}
return (
<div>
<form onSubmit={handleSubmitFile}>
<input
type="file"
onChange={handleFileInputChange}
/>
<button type="submit">
submit
</button>
</form >
</div >
)
}
ซึ่งก็เป็นโค้ดที่จะมีปุ่มเลือกไฟล์ แล้วก็ปุ่มอัปโหลดไฟล์นั้น หน้าตาปุ่มดังกล่าวก็ยังดูธรรมดา ๆ อย่างที่เห็น

นำ react-dropzone มาใช้กับโค้ดเดิมของเรา
ในส่วนของการนำ react-dropzone มาใช้มันก็มีอยู่ 2 วิธีตามเว็บไซต์ของ react-dropzone คือ เขียนแยกเป็นฟังก์ชัน กับ wrap เป็น component ไปเลย แต่ในที่นี้จะทำแบบแรกละกัน
โดยเมื่อนำโค้ดตัวอย่างจากบนเว็บไซต์มาใส่ในโค้ดของเรา แล้วก็ตกแต่งนิดหน่อยก็จะได้ออกมาหน้าตาตามนี้เลย
import React, { useState } from 'react';
import Axios from 'axios';
export default function Upload() {
Axios.defaults.withCredentials = true;
const [imageFile, setImageFile] = useState('');
const onDrop = useCallback((acceptedFiles) => {
handleFileInputChange(acceptedFiles[0]);
}, []);
const { getRootProps, getInputProps, isDragActive } = useDropzone({
onDrop,
accepts: "image/*",
multiple: false,
})
const handleFileInputChange = (file) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = () => {
setImageFile(reader.result);
}
}
const handleSubmitFile = (e) => {
e.preventDefault();
if (!imageFile) return;
Axios.put(`api url`, { data: imageFile});
}
return (
<div>
<div {...getRootProps()}>
<input {...getInputProps()} />
{
isDragActive ?
<p>Drop the files here ...</p> :
<p>Drag 'n' drop some files here, or click to select files</p>
}
</div>
<form onSubmit={handleSubmitFile}>
<button type="submit">
submit
</button>
</form >
</div >
)
}
โอ้โห มันโซอีซี่ โดยภายใน onDrop เราก็จะใส่ function handleFileInputChange ที่เราเคยได้เขียนไว้เพื่อส่งข้อมูลไฟล์ที่เราลากมาวางไปที่ฟังก์ชันของเรา ส่วนใน useDropzone ตรงนี้เราได้เพิ่ม accepts: “image/*” เข้าไป ซึ่งเป็นการบอกว่าเราจะรับไฟล์ประเภทรูปภาพ และ multiple: false เพื่อบอกว่ามันอัปโหลดได้ทีละไฟล์ ส่วนใน handleFileInputChange เองก็มีการเปลี่ยนแปลงเล็กน้อย โดย prop ที่เรารับมาเราจะเปลี่ยนเป็น file โดยมันจะส่งตรงไปที่ reader.readAsDataURL ไปเลย แล้วก็ลบ const file = e.target.files[0]; ไปได้เลยเพราะไม่ต้องใช้แล้ว เนื่องจาก react-dropzone ได้จัดการให้เราเป็นที่เรียบร้อยแล้ว
ส่วน component ของเรา เราก็เอาโค้ดจากบนเว็บไซต์มาใส่เลยเช่นกัน แล้วก็ลบในส่วนของ input ไปได้เลย เนื่องจากเรามี react-dropzone มาแล้วเช่นกัน
โดยผลลัพธ์จากออกมาดังนี้
(หน้าตาตอนยังไม่ได้ลากไฟล์มา)
(หน้าตาตอนมีไฟล์ถูกลากมาบน)
ตกแต่งด้วย CSS
บนหน้าลากวางไฟล์ของเรามันอาจจะยังดูไม่สวยไม่ชัดเจนเท่าไร เรามาลองตกแต่งมันด้วย CSS กันดูหน่อยดีกว่า
.dropzone {
height: 40vh;
margin: 1rem;
padding: 1rem;
border: 2px dashed lightgrey;
border-radius: 0.5rem;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
-webkit-transition: background-color 100ms linear;
-ms-transition: background-color 100ms linear;
transition: background-color 100ms linear;
}
.upload .active {
background-color: whitesmoke;
-webkit-transition: background-color 100ms linear;
-ms-transition: background-color 100ms linear;
transition: background-color 100ms linear;
}
โดย CSS ของเราก็จะมีเพียง 2 ส่วนคือ .dropzone คือหน้าตาของ drop ในเวลาปกติ และ .upload กับ .active คือหน้าตาของ dropzone เวลามีไฟล์ถูกลากมา
และในส่วนของ component เราก็จะเป็นการนำ css เหล่านั้นมาใช้ดังนี้
<div className="upload" >
<div
{...getRootProps()}
className={`dropzone ${isDragActive ? "active" : null}`}
>
<input {...getInputProps()} />
{
isDragActive ?
<p>Drop the files here ...</p> :
<p>Drag 'n' drop some files here, or click to select files</p>
}
</div>
<form onSubmit={handleSubmitFile}>
<button type="submit">
submit
</button>
</form >
</div >
ผลลัพธ์ที่ได้

ผลลัพธ์ที่ได้

สรุปสุดท้ายสิ่งที่ผู้อ่านจะได้รับ
เป็นยังไงกันบ้างครับสำหรับการใช้งาน react-dropzone เรียกได้ว่าง่ายสุด ๆ ไปเลยใช่ไหมครับ แต่สำหรับใครที่ยังต้องการตั้งค่าให้เหมาะกับงานของเรามากขึ้นเนี่ย มันยังมี PROPS กับ METHODS ให้ได้เล่นกันอีกมากมายเลย แล้วก็มีตัวอย่างแสดงวิธีการใช้งานที่ง่ายสุด ๆ สำหรับรายละเอียดเพื่อน ๆ ก็สามารถเข้าไปที่เว็บไซต์ https://react-dropzone.js.org/#src ได้เลย
อ้างอิงจาก
- Image Uploads to Cloudinary in React with Drag & Drop, สืบค้นเมื่อ 27 มกราคม 2565 จาก: https://www.youtube.com/watch?v=V8w7K1HdrFo&t=404s
-
react-dropzone, สืบค้นเมื่อ 4 กุมภาพันธ์ 2565 จาก: https://react-dropzone.js.org



