携手创作,共同成长!这是我参与「掘金日新计划 · 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)
使用步骤:
-
使用useRef能够创建一个ref对象,有current属性 {current: null}
const xxRef = useRef(null)
-
通过ref属性关联到某个DOM对象上 {current: DOM}
<div ref={xxRef}></div> -
可以通过 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 数据。