iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 19
2
Modern Web

TypeScript + React + 雜七雜八系列 第 19

【Day 19】React DnD,用 React 來實作 drag drop

  • 分享至 

  • xImage
  •  

大家好,今天的篇章要介紹的是 React DnD

一樣會延續前一天的專案結構接續下去進行修改,如果沒有參與到昨天的建置過程,這邊也有提供原始碼
https://github.com/littlehorseboy/typescript-react/tree/day18-draft-js


React DnD

React DnD 可以讓你用 React 的思維來實作 drag drop 的功能,筆者接下來會先參考 http://react-dnd.github.io/react-dnd/examples/dustbin/single-target 這裡的功能來實作

首先先安裝所需的東西

npm i react-dnd
npm i react-dnd-html5-backend
npm i classnames
npm i -D @types/classnames

Classnames,這是一個在 JS 之中要組 className 字串用的超好用第三方函式庫,是從 material-ui v3 時所用,雖然在 material-ui v4 時改用了更輕量的 clsx,不過筆者暫時沒有跟著換

定義 types,後一段會講到它的用途

+ src/components/ReactDnDPractice/itemTypes.ts

useDrag

+ src/components/ReactDnDPractice/Garbage/Garbage.tsx

這裡定義了 useDrag

const [{ isDragging }, drag] = useDrag({...

第二個參數 drag 是用來給要拖動的目標,掛到 div 的 ref 上用

然後是 useDrag 裡面的屬性

item: type 為必填,後續的 drop 組件在接收 drag 組件時,會先認這個值來做處理,所以用了剛剛定義的 itemTypes.ts 的內容,主要是為了集中管理,如果有不小心重複到可能會發生無法預期的後果,然後其它的定義屬性都是自由選配的,依照你的需求來讓 drop 組件讀到時做邏輯處理用

end: 監聽在拖動結束時,也就是滑鼠放開,所執行的事件

collect: 取得 DragSourceMonitor 所擁有的參數都要從這裡定義

接下來將他放進頁面中使用

+ src/components/ReactDnDPractice/ReactDnDPractice.tsx

然後執行看看

得到一個可以拖動的區塊,還要新增一塊區域能接受 garbage drop 至其中的區塊,來做互動

useDrop

+ src/components/ReactDnDPractice/GarbageCan/GarbageCan.tsx

這裡定義了 useDrop

const [{ canDrop, isOver }, drop] = useDrop({...

第二個參數 drop 是用來給要放置拖動組件的目標,掛到 div 的 ref 上用

然後是 useDrop 裡面的屬性

drop: 監聽接收到拖動組件時的事件,可以回傳內容,也可以用 void 來直接處理拖動組件內所夾帶的屬性

collect: 取得 DropTargetMonitor 所擁有的參數都要從這裡定義

接下來將他放進頁面中使用

呈現結果


以上就是筆者使用 React DnD 做的小小基本實例,用 React 的模式來實作 drag drop,也可以在 drop 當下改變 component 的 state,來 render 想要的結果,依靠 React DnD 提供的這些屬性就能非常方便的做出想要的功能(像是真的丟進垃圾桶裡面,並且還可以取出來,或是限制垃圾桶只能接一個垃圾這種)

最後附上原始碼
https://github.com/littlehorseboy/typescript-react/tree/day19-react-dnd


明天會介紹 Storybook,它可以用來管理你的 components


上一篇
【Day 18】Draft.js,用 React 來控制的 rich text editors,再更多功能
下一篇
【Day 20】Storybook
系列文
TypeScript + React + 雜七雜八30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言