hooks 存在的意义

  1. hooks 之间的状态是独立的,有自己独立的上下文,不会出现混淆状态的情况
  2. 让函数有了状态管理
  3. 解决了 组件树不直观、类组件难维护、逻辑不易复用的问题
  4. 避免函数重复执行的副作用

    应用场景

  5. 利用 hooks 取代生命周期函数

  6. 让组件有了状态
  7. 组件辅助函数
  8. 处理发送请求
  9. 存取数据
  10. 做好性能优化

    hooks API

    从 react 中引入

    1. useState

    给函数组件添加状态
  • 初始化以及更新组件状态
    1. const [count, setCount] = React.useState(0)

接收一个参数作为初始值,返回一个数组:第一个是状态变量,第二个是修改变量的函数

2. useEffect

副作用 hooks

  • 给没有生命周期的组件,添加结束渲染的信号

注意:

  • render 之后执行的 hooks

第一个参数接收一个函数,在组件更新的时候执行
第二个参数接收一个数组,用来表示需要追踪的变量,依赖列表,只有依赖更新的时候才会更新内容
第一个参数的返回值,返回一个函数,在 useEffect 执行之前,都会先执行里面返回的函数
一般用于添加销毁事件,这样就能保证只添加一个

  1. React.useEffect(() => {
  2. console.log('被调用了');
  3. return () => {
  4. console.log('我要被卸载了');
  5. }
  6. }, [count])
  7. // out:
  8. // 我要被卸载了
  9. // 被调用了

3. useLayoutEffect

和 useEffect 很类似
它的作用是:在 DOM 更新完成之后执行某个操作
注意:

  • 有 DOM 操作的副作用 hooks
  • 在 DOM 更新之后执行

执行时机在 useEffect 之前,其他都和 useEffect 都相同

useEffect 执行时机在 render 之后
useLayoutEffect 执行时机在 DOM 更新之后

4. useMemo

作用:让组件中的函数跟随状态更新
注意:优化函数组件中的功能函数

为了避免由于其他状态更新导致的当前函数的被迫执行

第一个参数接收一个函数,第二个参数为数组的依赖列表,返回一个值

  1. const getDoubleNum = useMemo(() => {
  2. console.log('ddd')
  3. return 2 * num
  4. }, [num])

5. useCallback

作用:跟随状态更新执行
注意:

  • 只有依赖项改变时才执行
  • useMemo( () => fn, deps) 相当于 useCallback(fn, deps)

不同点:

  1. useCallback 返回的是一个函数,不再是值
  2. useCallback 缓存的是一个函数,useMemo 缓存的是一个值,如果依赖不更新,返回的永远是缓存的那个函数
  3. 给子组件中传递 props 的时候,如果当前组件不更新,不会触发子组件的重新渲染

    6. useRef

    作用:长久保存数据
    注意事项:
  • 返回一个子元素索引,这个索引在整个生命周期中保持不变
  • 对象发生改变时,不通知,属性变更不重新渲染
  1. 保存一个值,在整个生命周期中维持不变
  2. 重新赋值 ref.current 不会触发重新渲染
  3. 相当于创建一个额外的容器来存储数据,我们可以在外部拿到这个值

当我们通过正常的方式去获取计时器的 id 是无法获取的,需要通过 ref

  1. useEffect(() => {
  2. ref.current = setInterval(() => {
  3. setNum(num => num + 1)
  4. }, 400)
  5. }, [])
  6. useEffect(() => {
  7. if (num > 10) {
  8. console.log('到十了');
  9. clearInterval(ref.current)
  10. }
  11. }, [num])

7. useContext

作用:带着子组件渲染
注意:

  • 上层数据发生改变,肯定会触发重新渲染
  1. 我们需要引入 useContext 和 createContext 两个内容
  2. 通过 createContext 创建一个 Context 句柄
  3. 通过 Provider 确定数据共享范围
  4. 通过 value 来分发数据
  5. 在子组件中,通过 useContext 来获取数据
  1. import React, { useContext, createContext } from 'react'
  2. const Context = createContext(null)
  3. export default function Hook() {
  4. const [num, setNum] = React.useState(1)
  5. return (
  6. <h1>
  7. 这是一个函数组件 - {num}
  8. // 确定范围
  9. <Context.Provider value={num}>
  10. <Item1 num={num} />
  11. <Item2 num={num} />
  12. </Context.Provider>
  13. </h1>
  14. )
  15. }
  16. function Item1() {
  17. const num = useContext(Context)
  18. return <div>子组件1 {num}</div>
  19. }
  20. function Item2() {
  21. const num = useContext(Context)
  22. return <div>子组件2 {num}</div>
  23. }

8. useReducer

作用:去其他地方借资源
注意:函数组件的 Redux 的操作

  1. 建数据仓库 store 和管理者 reducer
  2. 通过 useReducer(store,dispatch) 来获取 state 和 dispatch
  1. const store = {
  2. num: 10
  3. }
  4. const reducer = (state, action) => {
  5. switch (action.type) {
  6. case "":
  7. return
  8. default:
  9. return
  10. }
  11. }
  12. const [state, dispatch] = useReducer(reducer, store)

通过 dispatch 去派发 action

9. 自定义 hooks

放在 utils 文件夹中,以 use 开头命名
例如:模拟数据请求的 Hooks

  1. import React, { useState, useEffect } from "react";
  2. function useLoadData() {
  3. const [num, setNum] = useState(1);
  4. useEffect(() => {
  5. setTimeout(() => {
  6. setNum(2);
  7. }, 1000);
  8. }, []);
  9. return [num, setNum];
  10. }
  11. export default useLoadData;

减少代码耦合
我们希望 reducer 能让每个组件来使用,我们自己写一个 hooks
自定义一个自己的 LocalReducer

  1. import React, { useReducer } from "react";
  2. const store = { num: 1210 };
  3. const reducer = (state, action) => {
  4. switch (action.type) {
  5. case "num":
  6. return { ...state, num: action.num };
  7. default:
  8. return { ...state };
  9. }
  10. };
  11. function useLocalReducer() {
  12. const [state, dispatch] = useReducer(reducer, store);
  13. return [state, dispatch];
  14. }
  15. export default useLocalReducer;
  1. 引入 react 和自己需要的 hook
  2. 创建自己的hook函数
  3. 返回一个数组,数组中第一个内容是数据,第二个是修改数据的函数
  4. 暴露自定义 hook 函数出去
  5. 引入自己的业务组件


作者:小丞同学
链接:https://juejin.cn/post/7012492248587698206
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。