• React Hook - 自定义Hook的基本使用和案例练习


    自定义Hook

    自定义Hook基本使用

    自定义Hook本质上只是一种函数代码逻辑的抽取,严格意义上来说,它本身并不算React的特性

    例如有这样一个需求: 所有的组件在创建和销毁时都进行打印

    组件被创建: 打印组件被创建了;

    组件被销毁: 打印组件被销毁了;

    如果每个组件我们都单独编写是非常繁琐的, 并且有许多重复代码; 我们可以将实现这样逻辑相同的代码抽离为一个自定义的Hook

    import { useEffect } from 'react'
    
    // 自定义Hook
    function useLogLife() {
      useEffect(() => {
        console.log("组件被创建")
        return () => {
          console.log("组件被销毁")
        }
      }, [])
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在其他的组件中调用自定义Hook即可

    import React, { memo, useState, useEffect } from 'react'
    
    // 自定义Hook
    function useLogLife() {
      useEffect(() => {
        console.log("组件被创建")
        return () => {
          console.log("组件被销毁")
        }
      }, [])
    }
    
    // Home组件
    const Home = memo(() => {
      // 在组件中调用自定义Hook
      useLogLife()
    
      return (
        <h2>Home Page</h2>
      )
    })
    
    // About组件
    const About = memo(() => {
      // 在组件中调用自定义Hook
      useLogLife()
    
      return (
        <h2>About Page</h2>
      )
    })
    
    // App根组件
    const App = memo(() => {
      const [isShow, setIsShow] = useState(true)
    
      // 在组件中调用自定义Hook
      useLogLife()
    
      return (
        <div>
          <h2>App</h2>
          {/* 控制子组件显式隐藏 */}
          <button onClick={() => setIsShow(!isShow)}>切换</button>
          { isShow && <Home/> }
          { isShow && <About/> }
        </div>
      )
    })
    
    export default App
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    自定义Hook案例练习

    获取Context数据

    案例练习一: Context的共享, 例如我们有UserContext和TokenContext需要在多个组件中使用

    例如先定义两个Context

    import { createContext } from "react";
    
    const UserContext = createContext()
    const TokenContext = createContext()
    
    export {
      UserContext,
      TokenContext
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    使用定义的Context对App组件进包裹

    const root = ReactDOM.createRoot(document.querySelector("#root"))
    
    root.render(
      <UserContext.Provider value={{user: "chenyq", password: 1234}}>
        <TokenContext.Provider value={"abcdefg"}>
          <App/>
        </TokenContext.Provider>
      </UserContext.Provider>
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    将从Context中获取数据的操作封装到一个自定义Hook中

    import { useContext } from "react";
    import { TokenContext, UserContext } from "../context";
    
    function useUserToken() {
      const user = useContext(UserContext)
      const token = useContext(TokenContext)
    
      return [user, token]
    }
    
    export default useUserToken
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在其他要使用UserContext和TokenContext共享数据的组件中直接使用自定义Hook即可, 就不需要再单独的

    import React, { memo } from 'react'
    import useUserToken from './hooks/useUserToken'
    
    // Home组件
    const Home = memo(() => {
      const [user, token] = useUserToken()
    
      return (
        <h2>{user.user}-{user.password}-{token}</h2>
      )
    })
    
    // About组件
    const About = memo(() => {
      const [user, token] = useUserToken()
    
      return (
        <h2>{user.user}-{user.password}-{token}</h2>
      )
    })
    
    // App根组件
    const App = memo(() => {
      const [user, token] = useUserToken()
    
      return (
        <div>
          <h2>{user.user}-{user.password}-{token}</h2>
          <Home/>
          <About/>
        </div>
      )
    })
    
    export default App
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    获取窗口滚轮数据

    案例练习二: 在组件中监听鼠标滚轮的位置, 如多个组件中都需要监听鼠标滚轮的数据, 我们就可以封装到一个自定义的Hook中

    封装一个自定义的Hook监听鼠标滚动的数据, 由于监听的操作属于是副作用, 并且使用自定义Hook的组件如果重新渲染, 我们监听的操作是不需要重新执行的, 因此我们编写在Effect Hook中

    import { useEffect, useState } from "react";
    
    function useSrollPosition() {
      // 滚动的数据
      const [scrollX, setScrollX] = useState(0)
      const [scrollY, setScrollY] = useState(0)
    
      // 组件如果重新渲染, 我们监听的操作不需要重新执行, 因此在useEffect中编写
      useEffect(() => {
        // 监听的回调函数
        function handelScroll() {
          setScrollX(window.scrollX)
          setScrollY(window.scrollY)
        }
    
        // 监听的操作
        window.addEventListener("scroll", handelScroll)
    
        return () => {
          // 移除监听的操作
          window.removeEventListener("scroll", handelScroll)
        }
      }, [])
    
      // 返回监听滚动的数据
      return [scrollX, scrollY]
    }
    
    export default useSrollPosition
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    在需要监听的组件中调用自定义Hook, 就可以拿到滚动的数据

    import "./style.css"
    import React, { memo } from 'react'
    import useScrollPosition from './hooks/useScrollPosition'
    
    // App根组件
    const App = memo(() => {
      // 获取自定义Hook中监听滚动的数据
      const [scrollX, scrollY] = useScrollPosition()
      console.log(scrollX, scrollY)
    
      return (
        <div className="app">
          <h2>App</h2>
        </div>
      )
    })
    
    export default App
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
  • 相关阅读:
    linux Shell 命令行-05-test 检查某个条件是否成立
    SpringBoot+TKmybatis+mysql实现简单后台管理demo
    521. 最长特殊序列 Ⅰ
    win11网络连接正常,但是无法正常上网
    ChatGPT首次被植入人类大脑:帮助残障人士开启对话
    nuxt3踩坑
    STC不同系列单片机的软串口位时间函数差异
    数据赋能(102)——概念:数据分析、数据挖掘、数据洞察
    SCSS目录结构
    【学习笔记】 字符串基础 : 后缀自动机(基础篇)
  • 原文地址:https://blog.csdn.net/m0_71485750/article/details/126874856