react hook
只在最顶层使用 Hook
不要在循环,条件或嵌套函数中调用 Hook, 确保总是在你的 React 函数的最顶层调用他们。遵守这条规则,你就能确保 Hook 在每一次渲染中都按照同样的顺序被调用。这让 React 能够在多次的 useState
和 useEffect
调用之间保持 hook 状态的正确
不像 class 中的 this.setState
,更新 state 变量总是替换它而不是合并它。
Function Component:
function ProfilePage(props) {
setTimeout(() => {
// 就算父组件 reRender,这里拿到的 props 也是初始的
console.log(props);
}, 3000);
}
Class Component:
class ProfilePage extends React.Component {
render() {
setTimeout(() => {
// 如果父组件 reRender,this.props 拿到的永远是最新的。
// 并不是 props 变了,而是 this.props 指向了新的 props,旧的 props 找不到了
console.log(this.props);
}, 3000);
}
}
https://github.com/dt-fe/weekly/blob/master/95.%E7%B2%BE%E8%AF%BB%E3%80%8AFunction%20VS%20Class%20%E7%BB%84%E4%BB%B6%E3%80%8B.md
Hooks 也具有 capture value 特性
function MessageThread() {
const [message, setMessage] = useState("");
const showMessage = () => {
alert("You said: " + message);
};
const handleSendClick = () => {
setTimeout(showMessage, 3000);
};
const handleMessageChange = e => {
setMessage(e.target.value);
};
return (
<>
<input value={message} onChange={handleMessageChange} />
<button onClick={handleSendClick}>Send</button>
</>
);
}
(在线 Demo)
在点击 Send
按钮后,再次修改输入框的值,3 秒后的输出依然是 点击前输入框的值。这说明 Hooks 同样具有 capture value 的特性。
利用 useRef
可以规避 capture value 特性:
function MessageThread() {
const latestMessage = useRef("");
const showMessage = () => {
alert("You said: " + latestMessage.current);
};
const handleSendClick = () => {
setTimeout(showMessage, 3000);
};
const handleMessageChange = e => {
latestMessage.current = e.target.value;
};
}
只要将赋值与取值的对象变成 useRef
,而不是 useState
,就可以躲过 capture value 特性,在 3 秒后得到最新的值。
这说明了利用 Function Component + Hooks 可以实现 Class Component 做不到的 capture props、capture value,而且 React 官方也推荐 新的代码使用 Hooks 编写。