自定义hooks

本文介绍React自定义Hook的实现及应用案例,包括网络状态监测、输入框管理、网络请求封装等,展示了如何利用自定义Hook简化组件逻辑并提高代码复用率。

自定义hook

hook就是一个函数,有一些特定逻辑的封装函数

  1. 用于处理字符串(url)
  2. 数据格式化(日期)
  3. 业务逻辑性

自定义hook相对于普通js复用逻辑的抽离,然后可以在页面调用

自定义 Hook 是一个函数,主要解决一些状态逻辑重用的问题,其名称以 “use” 开头,其名称以 “use” 开头,函数内部调用其他的 Hooks。

hook是js函数但有两个额外的规则

  • 只能在函数最外层调用Hook。不能循环、条件判断或者子函数中调用
  • 只能在React的函数组件中调用Hook。不能在其他js函数中调用,但是可以在自定义的hook中

封装两个自定义hooks

  • 判断当前的网络情况
import React, { useState, useEffect } from 'react';
// 自定义一个hook  功能判断当前的网络情况
// 函数名要以use开头
// 函数中必须要用到内置hook函数
const useOnline = () => {
  const [online, setOnline] = useState(navigator.onLine)

  // 让它在第1次挂载时执行
  useEffect(() => {
    const onlineFn = () => setOnline(true)
    const offlineFn = () => setOnline(false)

    // js提供的监听事件
    window.addEventListener('online', onlineFn, false)
    window.addEventListener('offline', offlineFn, false)

    return () => {
      window.removeEventListener('online', onlineFn, false)
      window.removeEventListener('offline', offlineFn, false)
    }
  }, [])
  return online
}


const App = () => {
  const online = useOnline()
  return (
    <div>
      {
        online
          ?
          <div style={{ color: 'green' }}>在线</div>
          :
          <div>离线</div>
      }
    </div>
  );
}

export default App;

  • 自定义input输入
import React, { useEffect, useState } from 'react';

const useInput = ( defaultValue = "" ) => {
  const [value, setvalue] = useState(defaultValue)
  return {
    value,
    onchange: e => setvalue(e.target.value)
  }
}


const app = () => {
  const username = useInput()
  const password = useInput()
  return (
    <div>
      <input type="text" { ...username }/>
      <br/>
      <input type="text" { ...password }/>
      <br/>
      <button onClick={ () => {
        console.log(username.value, password.value);
      } }>
        登录
      </button>
    </div>
  )
}

  • 自定义网络封装hook
import axios from "axios";
import { useEffect, useState } from "react"
const useRequest = ({uri, method = "GET", data = {} }) => {
	const [res, setData] = useState([])
	const cb = () => {
		return axios({
			uri: uri,
			method,
			data
		}).then(res => {
			setData([...ret, ...ret.data.data.data])
		})
	}
	useEffect(() => {
		cb()
	},[]);
}
export default useRequest

以下案例来自React中自定义Hook的使用:

https://blog.youkuaiyun.com/weixin_45389051/article/details/107701508

  • 自定义context共享
export const UserContext = createContext()
export const TokenContext = createContext()

   <UserContext.Provider value={{name:'lvs'}}>
     <TokenContext.Provider value={{token:'#ccccc'}}>
     	<ContextShare/>
     </TokenContext.Provider>
   </UserContext.Provider>
import React, { useContext } from 'react'
import {UserContext,TokenContext} from '../App'
export default function useUserContext() {
  const user = useContext(UserContext)
  const token = useContext(TokenContext)
  return [user,token]
  return (
    <div>   
    </div>
  )
}
//将UserContext,TokenContext导入,然后通过useContext来赋值给我们定义的变量,然后给它return出去,这样我们在不同的组件也都能获取到
import React, { useContext } from 'react'
// 使用 Context内的内容
import useUserContext from '../hook/user-hook'
export default function ContextShare() {
  const [user,token] = useUserContext()
  console.log(user,token)
  return (
    <div>
    </div>
  )
}	
  • 自定义获取页面滚动位置hook
import React,{useState,useEffect} from 'react'
const useScrollPostion = () => {
  const [scrollPosition, setScrollPostion] = useState(0)
  useEffect(() => {
    const handleScroll = () => {
      setScrollPostion(window.scrollY)
    }
    document.addEventListener('scroll', handleScroll);
    return () => {
      document.removeEventListener('scroll', handleScroll)
    }
  },[])
   
   return scrollPosition
}
  • localstorage存储自定义hook
import React,{ useState, useEffect } from 'react'

export default function useLocalstoagehook(key) {

  const [name, setName] = useState(() => {
    const name = JSON.parse(localStorage.getItem(key))
    return name
  })

  useEffect(() => {
    // localStorage.setItem('name', name)
    localStorage.setItem(key, JSON.stringify(name))
  }, [name])
   
  return [name,setName]

  return (
    <div>
      
    </div>
  )
}
import React, { useState, useEffect } from 'react'

import useLocalstoagehook from '../hook/localstoagehook'

export default function CustomLocalStorage() {
  
  const [name,setName]= useLocalstoagehook('name')

  return (
    <div>
      {name}
      <button onClick={e => setName('lvs')}>设置</button>
    </div>
  )
}
### 创建和使用自定义React Hooks的方法 #### 什么是自定义Hooks自定义Hooks是一种在React中封装逻辑的方式,允许开发者将组件中的特定状态逻辑提取出来并重复使用。它们本质上是一个JavaScript函数,名字以`use`开头,并遵循React的规则[^1]。 #### 如何创建一个自定义Hook? 下面展示的是一个简单的例子——创建一个跟踪鼠标位置的自定义Hook `useMousePosition`: ```javascript import { useState, useEffect } from 'react'; function useMousePosition() { const [position, setPosition] = useState({ x: 0, y: 0 }); useEffect(() => { const handleMouseMove = (event) => { setPosition({ x: event.clientX, y: event.clientY }); }; document.addEventListener('mousemove', handleMouseMove); return () => { document.removeEventListener('mousemove', handleMouseMove); }; }, []); return position; } export default useMousePosition; ``` 此代码片段展示了如何通过`useState`和`useEffect`来创建一个能够追踪鼠标位置变化的自定义Hook[^4]。 #### 使用自定义Hook 一旦创建好自定义Hook,就可以像其他内置Hooks一样,在任何功能性组件里调用它。例如,我们可以这样在一个叫做`MouseTracker`的功能性组件中使用刚才定义好的`useMousePosition` Hook: ```javascript import React from 'react'; import useMousePosition from './useMousePosition'; const MouseTracker = () => { const mousePosition = useMousePosition(); return ( <p>Current Position: ({mousePosition.x}, {mousePosition.y})</p> ); }; export default MouseTracker; ``` 这段代码实现了显示鼠标的当前位置[^4]。 #### 防抖功能的实现 另一个常见的需求是对频繁触发的操作进行优化,比如搜索框输入时减少不必要的API请求次数。这里提供了一个防抖功能的例子 —— 自定义`useDebounce` Hook: ```javascript import React, { useEffect, useState } from 'react'; const useDebounce = (value, delay = 300) => { const [debouncedValue, setDebouncedValue] = useState(value); useEffect(() => { const handler = setTimeout(() => { setDebouncedValue(value); }, delay); return () => { clearTimeout(handler); }; }, [value, delay]); return debouncedValue; }; export default useDebounce; ``` 该Hook接受两个参数:需要被延迟处理的数据`value`以及等待时间间隔`delay`(默认为300毫秒)。当传入数据发生变化时启动定时器;如果再次改变,则取消之前的计时器重新计算新值的时间差[^5]。 #### 判断组件是否已卸载 有时我们需要知道某个组件在其生命周期内的某一时刻是否已经被移除掉。这可以通过如下所示的方式来完成: ```javascript import { useEffect, useRef } from 'react'; export function useUnmountRef(){ const unmountedRef = useRef(false); useEffect(() => { unmountedRef.current = false; return () => { unmountedRef.current = true; }; }, []); return unmountedRef; } ``` 在这个例子当中,我们利用了`useRef`保存了一个布尔类型的变量用来标记当前组件的状态,同时借助于`useEffect`提供的清理机制设置成true表示组件即将销毁[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MaxLoongLvs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值