接著昨天的進度,我們今天應該要為刪除按鈕加上功能,但是我看了一下我們的HomeListPage
這個 component 就想到,實務上我們最常遇到的問題是甚麼。
一定是各種奇怪的需求對吧,接下來我們先假設今天收到一個需求。
PM:我希望可以靈活的更換 Icon。
這時候看了一下 component 就會開始頭痛,因為我們這邊的 Icon 是寫死在 component 中的。
這時候我們可以怎麼做呢?
這邊介紹一下render props
,這是一個 React 的 pattern,我們先來看一下 React 官網上的介紹。
<DataProvider render={data => (
<h1>Hello {data.target}</h1>
)}/>
來看一下這段,DataProvider
這個 components 中,使用了 render 的方式回傳了一個新的 React 元件。
OK 現在我們知道這個方法可以回傳一個 component,我們回頭看一下剛剛的 component。
<button className="bg-red-700 rounded-md w-8 h-8 flex justify-center items-center text-white">
<Cross2Icon className="w-6 h-6" />
</button>
真巧!我們這邊使用 Radix icon 的元件剛好就是一個 component,那接下來就知道該怎麼做了吧!
首先我們先把 button 抽出來
const TodoBtn = ({ renderChildren }) => {
return (
<button className="bg-red-700 rounded-md w-8 h-8 flex justify-center items-center text-white">
{renderChildren()}
</button>
);
};
renderChilden
參數接收一個回傳 Component 的 funciton。
<TodoBtn
renderChildren={() => <Cross2Icon className="w-6 h-6" />}
/>
現在我們可以將 Component 作為 return 的值傳進TodoBtn
這個 Component 中,達到靈活抽換 Icon 的目的。
現在我們還需要在TodoBtn
這個 Component 中加上一個 onClick 方法,並且更新 JsDoc。
/**
* @param {function(): JSX.Element} renderChildren
* @param {function()} handleClick
* */
const TodoBtn = ({ renderChildren, handleClick }) => {
return (
<button
className="bg-red-700 rounded-md w-8 h-8 flex justify-center items-center text-white"
onClick={handleClick}
>
{renderChildren()}
</button>
);
};
現在我們就可以為刪除按鍵加上功能了!
我們建立一個function去處理移除事件。
/**
* @param {Event} e
* @param {Number} targetTodoId
*/
const handleDeleteBtnClick = (e, targetTodoId) => {
e.preventDefault();
e.stopPropagation();
newTodoList.splice(targetTodoId, 1)
setNewTodoList([...newTodoList])
};
前面我們原本使用const
宣告一個array,但是我們現在有更改array的需求,所以使用setState來儲存array,並且使用useEffect在render的時候將array存進newTodoList。
const [newTodoList, setNewTodoList] = useState([]);
useEffect(() => {
setNewTodoList((prev) => (prev = todoList?.map((e) => e)));
}, []);