在 Hook 概觀 的文章中,曾經寫過一個打造 Hook 的例子。複習一下,發現應該要修改命名為 useTimeout 來符合自動 Hook 判別。
// myTimeout => useTimeout
function useTimeout(delay) {
const [show, setShow] = React.useState(false);
React.useEffect(
() => {
let timer1 = setTimeout(() => setShow(true), delay * 1000);
return () => {
clearTimeout(timer1);
};
},
[]
);
return show;
}
function Vender() {
const [banana, takeBanana] = React.useState(0);
const timer1 = useTimeout(1)
const timer2 = useTimeout(3)
return (
//略
);
}
以下問答以之前的 useTimeout 例子為例。
請問我必須以「use」開頭命名我自定義的 Hook 嗎?
一個自定義的 Hook 不需要一個特定的宣告。我們可以決定它需要接受什麼參數,以及它應該回傳什麼(如果有的話)。換句話說,它像一個普通的 function。它的命名開頭應該總是為 use,所以你可以一眼就看出 Hook 的規則適用於它。
請問兩個 component 使用相同的 Hook 是共享 state 的嗎?
從 timer 裡面的例子就可以看到,它 delay 的時間不一樣,之間並沒有相互影響。
自定義的 Hook 是如何隔離 state 的?
同等於呼叫 useState 和 useEffect 多次,彼此建立起時都是獨立的。
官網的例子,使用 Selector 去選擇訂閱哪一個 id ,並用 setRecipientID 去更新 recipient 的最新狀態。
const friendList = [
{ id: 1, name: 'Phoebe' },
{ id: 2, name: 'Rachel' },
{ id: 3, name: 'Ross' },
];
function ChatRecipientPicker() {
const [recipientID, setRecipientID] = useState(1);
const isRecipientOnline = useFriendStatus(recipientID);
return (
<>
<Circle color={isRecipientOnline ? 'green' : 'red'} />
<select
value={recipientID}
onChange={e => setRecipientID(Number(e.target.value))}
>
{friendList.map(friend => (
<option key={friend.id} value={friend.id}>
{friend.name}
</option>
))}
</select>
</>
);
}
在打造你自己的 Hook 裡有提到一些對於新學習 React 的人可能不熟悉的東西,例如共享 stateful 邏輯會用到的
render props、higher-order component,或是 useState 的替代方案 reducer Hook,以及更複雜 component 會使用的 state 容器 Redux。將在之後的學習中補充。
以上今天。
參考資料:
https://zh-hant.reactjs.org/docs/hooks-custom.html