第一课:React的Hooks

npx是什么?

  • 避免安全全局模块

Hook规则

  • 只在最顶层使用Hook
  • 只在React函数中调用Hook

定义函数组件

javascript 复制代码
interface IHelloProps {
    message?: string
}

// const Hello = (props: IHelloProps) => {
//     return (
//         <div>
//             <h1>{props.message}</h1>
//         </div>
//     )
// }

const Hello: React.FC<IHelloProps> = (props) => {
    return (
        <div>
            <h1>{props.message}</h1>
        </div>
    )
}

export default Hello

hook的学习

老的hook

  • componetDidMount()
  • componetDidUpdate()
  • componetUnMonunt()
    新的Hook完全拥抱函数。

State Hook

在函数组件内部使用hook

  • 改变组件状态,组件里面记住状态的值。
javascript 复制代码
import React, {useState} from "react";
const LikeButton: React.FC = () => {
    const [obj, setObj] = useState({like: 0, on: true})
    return (
        <>
            <button onClick={() => setObj({like: obj.like + 1, on: obj.on})}>
                {obj.like}👍
            </button>
            <button onClick={() => setObj({like: obj.like, on: !obj.on})}>
                {obj.on ? 'ON' : 'OFF'}
            </button>
        </>
    )
}
export default LikeButton

Effect Hook

  • 无需清除的Effect
  • 使用useEffect完成标题的更新
  • 在老的class 中使用DiaMount 和 DidUpdate两个方法里面执行。

useEffect 在每次dom模型渲染之后,都会执行触发。

javascript 复制代码
    useEffect(() => {
        document.title = `点击了${obj.like}次`
    });
需要清除的Effect

注册的dom事件,要及时清除,否则会在组件每次渲染的时候,都会注册一次。

javascript 复制代码
import {useEffect, useState} from "react";


const MouseTracker: React.FC = () => {
    const [positions, setPositions] = useState({x: 0, y: 0})

    useEffect(() => {
        console.log('add effect:', positions.x)
        const updateMouse = (e: MouseEvent) => {
            console.log("inner")
            setPositions({x: e.clientX, y: e.clientY})
        }
        document.addEventListener('click', updateMouse)

        return () => {
            console.log('remove effect:', positions.x)
            document.removeEventListener('click', updateMouse)
        }
    });
    console.log('before render', positions.x)
    return (
        <p>鼠标位置:{positions.x}, {positions.y}</p>
    )
}

export default MouseTracker;
控制useEffect 的执行

可以使用最后一个参数数组[], 控制useEffect的执行时机,只有这些值发生变化,才会重新执行一次useEffect()

javascript 复制代码
    useEffect(() => {
        console.log('add button effect:', obj.like)
        document.title = `点击了${obj.like}次`
    }, [obj.like, on]);

自定义Hook

自定义hooks,必须以use开头。然后可以在多个组件中引入,互不干扰。

javascript 复制代码
import {useEffect, useState} from "react";

const useMousePosition = () => {
    const [positions, setPositions] = useState({x: 0, y: 0})

    useEffect(() => {
        console.log('add use effect:', positions.x)
        const updateMouse = (e: MouseEvent) => {
            console.log("use inner")
            setPositions({x: e.clientX, y: e.clientY})
        }
        document.addEventListener('mousemove', updateMouse)

        return () => {
            console.log('remove use  effect:', positions.x)
            document.removeEventListener('mousemove', updateMouse)
        }
    }, []);
    return positions
}

export default useMousePosition

在其它组件中使用:

  • 导入
    import useMousePosition from ".../hooks/useMousePosition";
  • 使用里面的值
    const positions = useMousePosition()

HOC 高阶组件(不太好的组件)

  • 可以对已有的组件进行转换成新组件。
  • 本身是一个函数,接收一个函数,返回另一个函数。

自定义hook完成HOC类似功能(更简单)

自定义:useURLLoader 功能。

javascript 复制代码
import axios from 'axios'
import {useEffect, useState} from "react";

const useURLLoader = (url: string, deps: any[] = []) => {

    const [data, setData] = useState<any>(null)
    const [loading, setLoading] = useState<boolean>(false)

    useEffect(() => {
        setLoading(true)
        axios.get(url).then(result => {
            setData(result.data)
            setLoading(false)
        })
    }, deps);
    return [data, loading]
}

export default useURLLoader


interface IShowResult {
    message: string
    status: string
}


通过count 控制组件再次重新请求
const [data, loading] = useURLLoader('https://dog.ceo/api/breeds/image/random', [count])
// data 是any 类型,强制转化成IShowResult
const dogResult = data as IShowResult

useRef(改变ref里面的current值,不会重新渲染dom)

修改Ref不会触发组件的重新渲染。

  • 使用用 ref 引用一个值
  • 通过 ref 操作 DOM
  • 避免重复创建 ref 的内容

特点:

  • 改变 ref.current 属性时,React 不会重新渲染组件。 所以不适合保存期望展示在屏幕上的信息。
  • 可以在 Effect 中读取和写入 ref
  • 可以在事件处理程序中读取和写入 ref
  • 不要在渲染期间写入或者读取 ref.current
javascript 复制代码
    const likeRef = useRef(0)
    - current 泛型的T
    
    function handleAlertClick() {
        setTimeout(() => {
            alert(`点击了${likeRef.current}次`)
        }, 3000)
    }
    
复制代码
useRef 可以模拟操作dom
javascript 复制代码
    const domRef = useRef<HTMLInputElement>(null)
    useEffect(() => {
        if(domRef && domRef.current){
            domRef.current.focus()
        }
    });
    <input type="text" ref={domRef}/>
相关推荐
ZC跨境爬虫9 分钟前
3D 地球卫星轨道可视化平台开发 Day13(卫星可视化交互优化+丝滑悬停聚焦)
前端·算法·3d·json·交互
qq_4198540515 分钟前
animation 和 transition
前端
weixin1997010801615 分钟前
《孔夫子旧书网商品详情页前端性能优化实战》
前端·性能优化
spring29979233 分钟前
SpringBoot返回文件让前端下载的几种方式
前端·spring boot·后端
木斯佳39 分钟前
前端八股文面经大全:正泰电气前端实习一面(2026-04-19)·面经深度解析
前端·面试·笔试·校招·面经
江-月*夜42 分钟前
vue3 wordcloud2.js词云使用
开发语言·javascript·vue.js
用户69371750013841 小时前
你每天用的 AI,可能真的被“投毒”了
前端·后端·ai编程
吴声子夜歌1 小时前
Vue3——Vuex状态管理
前端·vue.js·vue·es6
qq_12084093711 小时前
Three.js 工程向:Frustum Culling 与场景分块优化实战
前端·javascript
漫游的渔夫1 小时前
从 Fetch 到 RAG:为什么你的 AI 知识库总是“胡言乱语”?
前端·人工智能