接下來我們可以為 Todo 添加修改功能。
照慣例,我們需要先確認需求。
我希望當 user 進行編輯的時候,會彈出一個視窗,其中包含兩個欄位,標題 & 內容 & 2 個按鍵,用於關閉視窗 & 確認更新資料。
這時候我們可以先透過 createPortal 建立一個彈窗
import { createPortal } from "react-dom";
const Modal = ({ children, isVisible, close }) => {
if (!isVisible) return null;
return createPortal(
<div className="fixed top-0 left-0 right-0 bottom-0 bg-black/70 flex justify-center items-center">
<div className="w-1/2 min-w-[300px] bg-white p-5 rounded-[4px]">
<div className="w-full text-center">
{children}
<button
onClick={close}
className=" bg-red-500 text-white py-1 px-2 rounded-md"
>
關閉
</button>
</div>
</div>
</div>,
document.body
);
};
這邊的document.body
表示這個彈窗的生成位置,3 個參數分別表示其中的可編輯內文 / 彈窗是否顯示 / 關閉彈窗。
並且使用 custom hook 來包裝這個來包裝這個 modal 讓我們可以在任何地方使用這個功能。
const useModal = () => {
const [isVisible, setIsVisible] = useState(false);
const show = () => setIsVisible(true);
const hide = () => setIsVisible(false);
const RenderModal = ({ children }) => (
<Modal isVisible={isVisible} close={hide}>
{children}
</Modal>
);
return {
show,
hide,
RenderModal,
};
};
這邊可以看到透過 useModal 的方式將整個流程包裝成一個 custom hook,其中包含了開啟/關閉彈窗的 Method,RenderModal 表示內文渲染所包含的元素。
接下來我們需要使用這個 custom hook 來完成我們的 update 功能。
首先我們先回到 todo 的畫面加上下面這段,新增一個按鍵。
{
renderRecover && (
<TodoBtn
renderChildren={renderRecover}
handleClick={(e) => {
handleAction(e, todo, handleRecover);
}}
className={"bg-yellow-700"}
/>
);
}
這邊我們和前面的按鍵一樣,把icon & 功能往上拋至父層。
然後透過調用useModal讓我們點擊按鍵的時候顯示彈窗。
這邊透過解構賦值的方式,從useModal回傳的value中取出show ...等功能。
const { show, RenderModal, hide } = useModal();
當按鍵被點擊的時候,顯示視窗。
const handleEditBtnClick = (item) => {
show();
};