Hook

1.Hook可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。

2.Hook 使你在无需修改组件结构的情况下复用状态逻辑。

3.Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数。

4.Hook 使用规则:
只能在函数最外层调用 Hook。不要在循环、条件判断或者子函数中调用。
只能在 React 的函数组件中调用 Hook。不要在其他 JavaScript 函数中调用。(还有一个地方可以调用 Hook —— 就是自定义的 Hook 中)

5.useState 是允许你在 React 函数组件中添加 state 的 Hook

6.什么时候我会用 Hook? 如果你在编写函数组件并意识到需要向其添加一些 state,以前的做法是必须将其转化为 class。
现在你可以在现有的函数组件中使用 Hook。

7.useState:例 const [count, setCount] = useState(0);
调用useState,它会定义一个state变量,变量名由你决定,此处为count,唯一的参数就是初始变量的值。返回值为:当前 state 以及更新 state 的函数,此处为setCount。
在函数中,可以直接使用count进行访问 如:<p>You clicked {count} times</p>
在函数中,我们已经有了 setCount 和 count 变量,所以我们不需要 this便可直接访问。

为什么要使用解构赋值?
其实在调用useState的时候,返回了一个数组,数组中含有两个值,利用解构赋值一一对应。

8.Effect Hook 可以让你在函数组件中执行副作用操作
数据获取,设置订阅以及手动更改 React 组件中的 DOM 都属于副作用。
可以把 useEffect Hook 看做 componentDidMount,componentDidUpdate 和 componentWillUnmount 这三个函数的组合。

无需清除的effect:发送网络请求,手动变更 DOM,记录日志,这些都是常见的无需清除的操作。
通过使用这个 Hook,你可以告诉 React 组件需要在渲染后执行某些操作。
将 useEffect 放在组件内部让我们可以在 effect 中直接访问 count state 变量。
React 保证了每次运行 effect 的同时,DOM 都已经更新完毕
与 componentDidMount 或 componentDidUpdate 不同,使用 useEffect 调度的 effect 不会阻塞浏览器更新屏幕,这让你的应用看起来响应更快。

需要清除的effect:
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
// Specify how to clean up after this effect:
return function cleanup() {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
由于添加和删除订阅的代码的紧密性,所以 useEffect 的设计是在同一个地方执行。
如果你的 effect 返回一个函数,React 将会在执行清除操作时调用它。这个清除机制是可选的,没个effect都可以返回清除函数。
useEffect 会在调用一个新的 effect 之前对前一个 effect 进行清理
如果某些特定值在两次重渲染之间没有发生变化,你可以通知 React 跳过对 effect 的调用,只要传递数组作为 useEffect 的第二个可选参数即可,数组值即为记录的state变量。
如果想执行只运行一次的 effect(仅在组件挂载和卸载时执行),可以传递一个空数组([])作为第二个参数。

9.Hook规则
只在最顶层使用 Hook,不要在循环,条件或嵌套函数中调用 Hook
只在 React 函数中调用 Hook,不要在普通的 JavaScript 函数中调用 Hook

React 怎么知道哪个 state 对应哪个 useState?答案是 React 靠的是 Hook 调用的顺序。Hook 的调用顺序在每次渲染中都是相同的。

10.自定义Hook
自定义 Hook 是一个函数,其名称以 “use” 开头,函数内部可以调用其他的 Hook
自定义 Hook 是一种重用状态逻辑的机制,所以每次使用自定义 Hook 时,其中的所有 state 和副作用都是完全隔离的。

11.useReducer 的 Hook,使用 reducer 的方式来管理组件的内部 state

12.HookApi
基础:
useState:
惰性初始 state:如果初始 state 需要通过复杂计算获得,则可以传入一个函数,在函数中计算并返回初始的 state,此函数只在初始渲染时被调用.
const [state, setState] = useState(() => {
const initialState = someExpensiveComputation(props);
return initialState;
});

useEffect:

useContext:
const value = useContext(MyContext);
当组件上层最近的 <MyContext.Provider> 更新时,该 Hook 会触发重渲染,并使用最新传递给 MyContext provider 的 context value 值

额外:
useReducer


useCallback
useMemo

useCallback(fn, deps) 相当于 useMemo(() => fn, deps)。回调函数仅在某个依赖项改变时才会更新。


useRef

useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref 对象在组件的整个生命周期内保持不变。

利用uesRef可以实现访问历史及未来state值;同时可以利用此特性保存某个 prop,某个 state 变量,甚至一个函数

useImperativeHandle
useLayoutEffect
useDebugValue

13.HOOKS FAQ
我应该使用单个还是多个 state 变量?推荐把 state 切分成多个 state 变量,每个变量包含的不同值会在同时发生变化.

如何获取上一轮的 props 或 state?可以 通过 ref 来手动实现

有类似 forceUpdate 的东西吗?可以用一个增长的计数器来在 state 没变的时候依然强制一次重新渲染

如何测量 DOM 节点?获取 DOM 节点的位置或是大小的基本方式是使用 callback ref。每当 ref 被附加到一个另一个节点,React 就会调用 callback。