对React Hook基本了解

React Hook及自定义Hook 基本介绍

1.什么是Hook

Hook 是特殊的函数,只在 React渲染时有效。它们能让你 "hook" 到不同的 React 特性中去。我们可以通过hook把需要的状态、副作用方法钩进来,放在函数内部使用。让原本呆板的react函数拥有状态和生命周期。

2.useState 让函数拥有内部状态

组件通常需要根据交互更改屏幕上显示的内容。输入表单应该更新输入字段,当点击轮播图"下一个"应该更改显示的图片,或者点击一个按钮使一个显示的数字加一,都要使用到useState。

javascript 复制代码
import { useState } from 'react'
​
// 状态:随着交互变化的数据
function App() {
    const [count, setCount] = useState(0)
    const handleClick = () => {
        setCount(count + 1)  // 把函数重新走一遍 有记忆功能 每次走一遍之后修改count的内容
    }
    return (
        <>
            <button onClick={handleClick}>点击</button>
            {count}
        </>
    )
}
​
export default App
​

count是一个state变量,setCount是对应的setter函数,[..,..]为数组结构,允许从数组中读取值,useState的唯一参数是state变量的初始值。在这个例子中,count的变量是0。

State是隔离且私有的,如果同一个组件被调用两次,两个副本之间是相互隔离的。

State是一张快照 ,当状态放生更新时,编译器会对多次状态修改进行自动批处理 (React会等到事件处理函数中的所有代码都运行完毕之后再处理state更新,队列都执行完毕后,在进行UI更新),本例子中的count在按钮点击之后不会递增三次,由于快照尽管你调用了三次setCount(count + 1),但在这次渲染的事件处理函数中 number 会一直是0

javascript 复制代码
import { useState } from 'react'
​
function App() {
    let num = 0
    const [count, setCount] = useState(0) 
    const handleClick = () => {
        setCount(count + 1) //0 + 1
        setCount(count + 1) //0 + 1
        setCount(count + 1) //0 + 1
        console.log(count) 
    }
    console.log(count)
    return (
        <>
            <button onClick={handleClick}>点击</button>
            {count} {/* 渲染的是最后一次的结果 */}
        </>
    )
}
​
export default App

3.useEffect 让函数可以执行副作用

函数副作用是指函数在正常工作任务之外对外部环境所施加的影响。具体地说,函数副作用是指函数被调用,完成了函数既定的计算任务,但同时因为访问了外部数据,尤其是因为对外部数据进行了写操作,从而一定程度地改变了系统环境。函数的副作用也有可能是发生在函数运行期间,由于对外部数据的改变,导致了同步运行的外部函数受到影响。

javascript 复制代码
import { useEffect, useState } from 'react' //声明
​
function App() {
    const [count, setCount] = useState(0)
    const handleClick = () => {
        setCount(count + 1)
    }
    useEffect(() => {
        console.log(count)
    }, [count]) //count依赖项,只有count改变的时候才会触发
    //当空数组的时候只有初始的时候会触发,更新的时候不会触发
    useEffect(() => {
        console.log(count)
    }, [])
​
    return (
        <>
            <button onClick={handleClick}>点击</button>
            {count}
        </>
    )
}
​
export default App
​

useEffect 触发时机:jsx渲染完毕之后

useEffect 参数分为三种:

1.无参数useEffect(() => {console.log(count)}) 初始时触发一次 当状态发生更新时再触发

2.空数组参数useEffect(() => {console.log(count)}, []) 只有初始的时候会触发 更新的时候不会触发

3.依赖项useEffect(() => {console.log(count)}, [count]) 初始时触发一次 当依赖项发生改变时再触发

4.useContext 让函数可以深层传递参数

Context允许父组件向其下层无论多深的任何组件提供信息,而无需通过peops显示传递

javascript 复制代码
import { createContext, useContext, useState } from 'react'
​
const Context = createContext(0)
​
function App() {
    const [count, setCount] = useState(0)
    const handleClick = () => {
        setCount(count + 1)
    }
    return (
        <>
            <div>hello App</div>
            <button onClick={handleClick}>点击</button>
            <Context.Provider value={count}>
                {/* 需要传递的参数 value 传入的参数可以是任何数据类型 */}
                <Head />
            </Context.Provider>
        </>
    )
}
function Head() {
    return (
        <>
            <div>hello Head</div>
            <Title />
        </>
    )
}
function Title() {
    const value = useContext(Context) //在需要使用的组件中拿到数据
    return (
        <>
            <div>hello Title</div>
            {value}
        </>
    )
}
​
export default App
​

createContext(0) 括号中的0为初始值,当没有传递参数时得到的就是默认值

Countext可以传递随着状态发生改变的值

5.useRef 可通过ref操作DOM

javascript 复制代码
function App() {
    const [count, setCount] = useState(0)
    let num = useRef(0) 
    const handleClick = () => {
        // 更行数据之后 函数回重新渲染 num会使用当前作用域下的值0 所以每次运行之后都是1 为了使num具有记忆功能 引入ref
        setCount(count + 1)
        num.current++
        console.log(num.current)
    }
    return (
        <>
            <button onClick={handleClick}>点击</button>
            {count}
        </>
    )
}

你可以用 ref.current 属性访问该 ref 的当前值

ref再更改时不会触发重新渲染。 设置 state 会重新渲染组件,更改ref 不会!

你可以在渲染过程之外修改和更新current的值 ,而对于state,只能使用state设置函数来修改state变量,从而排队重新渲染。可以把current和state搭配使用,这样就可以渲染出current,如果只用ref则不能实现current修改后直接渲染出来。

javascript 复制代码
//通过ref操作DOM
import { forwardRef, useRef, useState } from 'react'
​
//当组件添加ref属性的时候,需要forwardRef进行转发,forwardRef让你的组件通过ref向父组件公开DOM节点
​
const MyInput = forwardRef(function MyInput( ref) {
    return (
        <>
            <input type="text" ref={ref} />
        </>
    )
})
​
function App() {
    let ref = useRef(null)
    const handleClick = () => {
        ref.current.focus()
        ref.current.style.background = 'yellow'
        ref.current.value='123'
    }
    return (
        <>
            <button onClick={handleClick}>点击</button>
            <MyInput ref={ref}/>
        </>
    )
}
​
export default App
​

由于 React 会自动处理更新DOM以匹配你的渲染输出,因此你在组件中通常不需要操作DOM。但是,有时你可能需要访问由 React管理的 DOM 元素 ------ 例如,让一个节点获得焦点、滚动到它或测量它的尺寸和位置。在React 中没有内置的方法来做这些事情,所以你需要一个指向 DOM节点的 ref来实现。

当组件添加ref属性的时候,需要forwardRef进行转发,forwardRef让你的组件通过ref向父组件公开DOM节点

6.什么是自定义HOOK

自定义hook是一个函数,函数内部可以调用其他hook函数,且以use开头命名,主要作用是对逻辑功能进行封装处理,达到一种复用能力

手动实现显示鼠标坐标的自定义hook

javascript 复制代码
import { useEffect, useState } from 'react'
​
//实现一个实时获取鼠标的自定义Hook
function useMouse() {
    const [state, setState] = useState({
        pageX: NaN,
        pageY: NaN,
    })
    useEffect(() => {
        function move(e) {
            setState({
                pageX: e.pageX,
                pageY: e.pageY,
            })
        }
        // 创建事件
        document.addEventListener('mousemove', move)
        return () => {
            //清理工作 删除事件
            document.removeEventListener('mousemove', move)
        }
    }, [])
​
    return state
}
function App() {
    const mouse = useMouse()
    return (
        <>
            <div>
                {mouse.pageX} {mouse.pageY}
            </div>
        </>
    )
}
​
export default App

第三方Hooks:ahooks react-use

相关推荐
子兮曰4 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰4 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万4 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝4 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋4 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁4 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95274 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大4 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师4 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学4 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端