react笔记(十二)—— 自定义hooks

960 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第12天,点击查看活动详情

前言

大家好呀,我是L同学。在上篇文章react笔记(十一)—— useEffect依赖项中,我们学习了useEffect依赖是一个空数组、useEffect不要对依赖项撒谎、useEffect清理副作用、useState-回调函数参数等相关知识点。在本篇文章中,我们将学习到自定义hooks、使用useEffect发送请求、使用useRef操作DOM、useContext等相关知识点。

自定义hooks

除了使用内置的 Hooks 之外,还可以创建自己的 Hooks(自定义 Hooks),useXxx。自定义hooks能实现状态的逻辑复用。自定义hooks的使用场景是将组件状态逻辑提取到可重用的函数(自定义 Hooks)中,实现状态逻辑复用。内置 Hooks 为函数组件赋予了 class 组件的功能;在此之上,自定义 Hooks 针对不同组件实现不同状态逻辑复用。

自定义 Hooks 是一个函数,约定函数名称必须以 use 开头,React 就是通过函数名称是否以 use 开头来判断是不是 Hooks。Hooks 只能在函数组件中或其他自定义 Hooks 中使用,否则,会报错。自定义 Hooks 用来提取组件的状态逻辑,根据不同功能可以有不同的参数和返回值(就像使用普通函数一样)。

// 使用hooks实现猫跟着鼠标移动
import { useEffect, useState } from 'react'
export default function useMouse() {
  const [position, setPosition] = useState({
    x: 0,
    y: 0,
  })

  useEffect(() => {
    const move = (e) => {
      setPosition({
        x: e.pageX,
        y: e.pageY,
      })
    }
    document.addEventListener('mousemove', move)
    return () => {
      document.removeEventListener('mousemove', move)
    }
  }, [])
  return position
}

useEffect发送请求

在组件中,可以使用 useEffect Hook 发送请求获取数据(side effect)。需要注意的是effect 只能是一个同步函数,不能使用 async。如果 effect 是 async 的,此时返回值是 Promise 对象。这样的话,就无法保证清理函数被立即调用。为了使用 async/await 语法,可以在 effect 内部创建 async 函数,并调用。

// 错误演示:

// 不要给 effect 添加 async
useEffect(async () => {
    const res = awiat xxx()
    return ()=> {
        
    }
}, [])

// 正确使用
useEffect(() => {

  async function fetchMyAPI() {
    let url = 'http://something/' + productId
    let config = {}
    const response = await myFetch(url)
  }

  fetchMyAPI()
}, [productId])

useRef-操作DOM

我们可以使用useRef操作DOM,获取 DOM。useRef返回一个带有 current 属性的可变对象,通过该对象就可以进行 DOM 操作了。

在获取 DOM 时,参数一般都设置为 null。返回值是包含 current 属性的对象。只要在 React 中进行 DOM 操作,都可以通过 useRef Hook 来获取 DOM(比如,获取 DOM 的宽高等)。useRef不仅仅可以用于操作DOM,还可以操作组件。

const inputRef = useRef(null)

使用步骤:

  1. 使用useRef能够创建一个ref对象,有current属性 {current: null}

    const xxRef = useRef(null)

  2. 通过ref属性关联到某个DOM对象上 {current: DOM}

    <div ref={xxRef}></div>

  3. 可以通过 xxRef.current访问到对应的DOM

const App = () => {
  const inputRef = useRef(null)
  const add = () => {
    console.log(inputRef.current.value)
  }
  return (
    <section className="todoapp">
      <input type="text" placeholder="请输入内容" ref={inputRef} />
      <button onClick={add}>添加</button>
    </section>
  )
}
export default App

useContext-context

Context可以实现跨组件传递数据,而不必在每个级别手动传递 props,简化组件之间的数据传递过程。

Context 对象包含了两个组件

  • <Context.Provider value>:通过 value 属性提供数据。
  • <Context.Consumer>:通过 render-props 模式,在 JSX 中获取 Context 中提供的数据。

如果提供了 Provider 组件,Consumer 获取到的是 Provider 中 value 属性的值。如果没有提供 Provider 组件,Consumer 获取到的是 createContext(defaultValue) 的 defaultValue 值。

在函数组件中,获取 Context 中的值。要配合 Context 一起使用。

useContext Hook<Context.Consumer> 的区别:获取数据的位置不同:

  • <Context.Consumer>:在 JSX 中获取 Context 共享的数据。
  • useContext:在 JS 代码中获取 Context 的数据。

useContext 的参数:Context 对象,即:通过 createContext 函数创建的对象。

useContext 的返回值:Context 中提供的 value 数据。