今天要來聊 React hooks,Hooks 在 React 16.8 時推出,它提供了更低的學習曲線、更高的可讀性和更輕鬆的 debug。這篇文章會預設你已經看過 react 的hooks 文章,並且對 hooks 有基本的了解,然後我們會以面試的問答方式來討論幾個常見的 hooks,讀者可以先試著自己答看看,在看答案喔!
回答:hooks 有兩個規則,第一個是 hooks 只能在最高層被呼叫,代表 hooks 不能在 if condition, function 等情況下呼叫。第二個是 hooks 只能在 React functional component 或是 custom hooks 中呼叫,不能在 Js function 中使用。
follow up: 為什麼 hooks 只能在最高層被呼叫?
回答:因為 React 依靠 hooks 呼叫的順序。
https://reactjs.org/docs/hooks-rules.html#explanation
function Test({ name, children = null }) {
console.log("children", children);
useEffect(() => {
console.log(`${name} effect`);
return () => {
console.log(`${name} cleanup`);
};
});
return children;
}
function App() {
return (
<Test name="parent">
<Test name="child">123</Test>
</Test>
);
}
範例在這
解題思路:在 React 16 中,mount 的順序是父組建 => 子組建,effect 的順序是子組建 => 父組建。
注意:child render 兩次,因為使用 strict mode 中並且在 dev 環境中,實際 prod 環境只會 render 一次。
function App() {
const ref = useRef(null);
const [state, setState] = useState(1);
useEffect(() => {
setState(2);
}, []);
console.log("text", ref.current?.textContent);
return (
<div>
<div ref={state === 1 ? ref : null}>1</div>
<div ref={state === 2 ? ref : null}>2</div>
</div>
);
}
範例在[這](https://codesandbox.io/s/objective-wood-hqxpqx?file=/src/App.js:111-413)
解題思路:ref 有兩個重點,
follow up,如果把 useEffect 裡面的[]拿掉,結果會改變嗎?
如果對 useRef 還是有點不熟悉的話,筆者很推這篇文章,我覺得他用很淺顯的字句把 useRef 的用途講得很仔細!
解題思路:useImperativeHandle 可以讓父組件輸出任意數據,其必須要和 forwardRef 一起使用。
下面看範例:
透過 useImperativeHandle,我們讓父層可以控制子層的 focus。
// 透過forwardRef 讓FancyInput组件可以接收ref
const FancyInput = React.forwardRef(function FancyInput(props, ref) {
const inputRef = useRef();
// 命令式的给`ref.current`focus
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus()
}
}));
return <input ref={inputRef} ... />
})
// Example组件作为父组件
function Example() {
const fancyInputRef = useRef()
const focus = () => {
fancyInputRef.current.focus()
}
return (
<>
<FancyInput ref={fancyInputRef} />
</>
)
}
希望這些題目,能夠讓讀者對 hooks 有一些更深的理解,至於其他文內沒有提到的hooks就等讀者自己去研究摟~~~我們明天見!
https://juejin.cn/post/7094651577117442056
https://segmentfault.com/a/1190000040758640
follow up,如果把 useEffect 裡面的[]拿掉,結果會改變嗎?
原本以為不會變,因 useState
會判斷前後值若一樣就不會 re-render,結果沒想到會變,但只 re-render 一次,不知道為何會這樣