React Hooks - 自定义hooks
Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性
Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数。Hook 不能在 class 组件中使用 —— 这使得你不使用 class 也能使用 React
react hooks
useEffect
useEffect 就是一个 Effect Hook,给函数组件增加了操作副作用的能力
它跟 class 组件中的 componentDidMount、componentDidUpdate 和 componentWillUnmount 具有相同的用途
在使用时我们传递一个数组,useEffect 会在数组内的数据发生变化时重新执行
useEffect 函数需返回一个清除函数,清除函数会在组件卸载前执行。另外,如果组件多次渲染(通常如此),则在执行下一个 effect 之前,上一个 effect 就已被清除
1 | useEffect(() => { |
如果想执行只运行一次的 effect(仅在组件挂载和卸载时执行),可以传递一个空数组([])作为第二个参数。
useState
useState 会返回一对值:当前状态和一个让你更新它的函数,你可以在事件处理函数中或其他一些地方调用这个函数。
更新函数操作是完全替换,而非合并操作
1 | const [count, setCount] = useState(0) // 初始化 count |
useContext 上下文对象
用来接收由React.createContext() 创建的 context对象,并返回context对象的当前值,父组件需要有 <MyContext.Provider>
包裹着,值由 value 确定
1 | const themes = { |
useReducer
useReducer 是 useState 的替代方案,它接收一个形如 (state, action) => newState 的 reducer,并返回当前的 state 以及与其配套的 dispatch 方法
1 | const initialState = {count: 0}; |
在上述例子中,当修改 state 里面的值的时候,会通过dispatch 传递一个比较复杂的值作为 reducer 方法中的 action,在reducer 内部通过 action 的值来进行代码运算,返回出新的值
useCallback
React useCallbackHook 返回一個記憶化的回調函數。這使我們能夠隔離資源密集型功能,以便它們不會在每次渲染時自動運行。
使用useCallback鉤子來防止函數被重新創建,除非有必要。
1 | const addTodo = useCallback(() => { |
当组件内容发生变化重新渲染的时候,如果 todos
没有发生变化的话,addTodo 函数不会重新创建
useMemo
React useCallbackHook 返回一個記憶化的值,它仅会在某个依赖项改变时才重新计算 memoized 值。这种优化有助于避免在每次渲染时都进行高开销的计算
传入 useMemo 的函数会在渲染期间执行。请不要在这个函数内部执行不应该在渲染期间内执行的操作
1 | const Todo = ({ todos }) => { |
以上 Todo 组件仅会在 todos 参数发生变化时才会重新计算渲染,如果传入内容有函数,可以和 useCallback 接合,实现值的缓存
useRef
useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref 对象在组件的整个生命周期内持续存在。
useRef 既可以用来存储 dom 对象,也可以用来存储单个的值
当 ref 对象内容发生变化时,useRef 并不会通知你。变更 .current 属性不会引发组件重新渲染。
1 | const ref = useRef(1) |
useImperativeHandle 和 forwardRef
useImperativeHandle 可以让你在使用 ref 时自定义暴露给父组件的实例值。
父组件使用 forwardRef 来接收子组件暴露出的实例值
1 | function FancyInput(props, ref) { |
useLayoutEffect
其函数签名与 useEffect 相同,但它会在所有的 DOM 变更之后同步调用 effect。可以使用它来读取 DOM 布局并同步触发重渲染。在浏览器执行绘制之前,useLayoutEffect 内部的更新计划将被同步刷新。
useDebugValue
useDebugValue 可用于在 React 开发者工具中显示自定义 hook 的标签。
1 | function useFriendStatus(friendID) { |
useDeferredValue
useDeferredValue 接受一个值,并返回该值的新副本,该副本将推迟到更紧急地更新之后。如果当前渲染是一个紧急更新的结果,比如用户输入,React 将返回之前的值,然后在紧急渲染完成后渲染新的值。
该 hook 与使用防抖和节流去延迟更新的用户空间 hooks 类似。使用 useDeferredValue 的好处是,React 将在其他工作完成(而不是等待任意时间)后立即进行更新,并且像 startTransition 一样,延迟值可以暂停,而不会触发现有内容的意外降级。
1 | function Typeahead() { |
useTransition
返回一个状态值表示过渡任务的等待状态,以及一个启动该过渡任务的函数。
isPending 指示过渡任务何时活跃以显示一个等待状态:
startTransition 用来启动过渡任务
1 | function App() { |
useId
useId 是一个用于生成横跨服务端和客户端的稳定的唯一 ID 的同时避免 hydration 不匹配的 hook。
自定义 Hooks
在知道上述 hooks 之后,react 也支持我们自定义 hooks 操作。
自定义 hooks 主要是用来 提取共享逻辑,优化代码结构。
1 | const useUserInfo = () => { |