返回顶部
首页 > 资讯 > 精选 >怎么构建自己的react hooks
  • 933
分享到

怎么构建自己的react hooks

2023-06-15 01:06:02 933人浏览 独家记忆
摘要

这篇文章主要介绍怎么构建自己的React hooks,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1. 常用的一个 hooks官方中提供了几个内置的钩子,我们简单了解下他们的用法。1.1 useState: 状态钩子

这篇文章主要介绍怎么构建自己的React hooks,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

1. 常用的一个 hooks

官方中提供了几个内置的钩子,我们简单了解下他们的用法。

1.1 useState: 状态钩子

需要更新页面状态的数据,我们可以把他放到 useState 的钩子里。例如点击按钮一下,数据加 1 的操作:

const [count, setCount] = useState(0);return (<>    <p>{ count}</p>    <button onClick = {        () => setCount(count + 1)    }> add 1 </button>    </>);

typescript 的体系中,count 的类型,默认就是当前初始值的类型,例如上面例子中的变量就是 number 类型。如果我们想自定义这个变量的类型,可以在 useState 后面进行定义:

const [count, setCount] = useState<number | null>(null); // 变量count为number类型或者null类型

同时,使用 useState 改变状态时,是整个把 state 替换掉的,因此,若状态变量是个 object 类型的数据,我只想修改其中的某个字段,在之前 class 组件内调用 setState 时,他内部会自动合并数据。

class Home extends React.Component {    state = {        name: 'wenzi',        age: 20,        score: 89    };    update() {        this.setState({            score: 98        }); // 内部自动合并    }}

但在 function 组件内使用 useState 时,需要自己先合并数据,然后再调用方法,否则会造成字段的丢失。

const [person, setPerson] = useState({    name: 'wenzi',    age: 20,    score: 89});setPerson({    ...person,    {        score: 98    }}); // 先合并数据 { name: 'wenzi', age: 20, score: 98 }setPerson({    score: 98}); // 仅传入要修改的字段,后name和age字段丢失

1.2 useEffect: 副作用钩子

useEffect 可以看做是 componentDidMount,componentDidUpdate 和 componentWillUnmount 这三个函数的组合。

useEffect 钩子在组件初始化完毕时,一定会执行一次,在组件重新渲染的过程中,是否还要 update,还要看传入的第 2 个参数。

  • 当只有回调函数这一个参数时,组件的每次更新,回调都会执行;

  • 当有 2 个参数时,只有第 2 参数里的数据发生变化时,回调才执行;

  • 只想在组件初始化完毕时只执行一次,第 2 个参数可以传入一个空的数组

我们可以看下这个例子,无论点击 add按钮 还是 settime按钮 ,useEffect 的回调都会执行:

const Home = () => {    const [count, setCount] = useState(0);    const [nowtime, setNowtime] = useState(0);    useEffect(() => {        console.log('count', count);        console.log('nowtime', nowtime);    });    return ( <>        <p>count: {count} </p>        <p>nowtime: {nowtime} </p>        <button onClick = {() => setCount(count + 1)}> add 1 </button>        <button onClick = {() => setNowtime(Date.now())} > set now time </button>    </>);};

若改成下面的这样,回调仅会在 count 发生变化时才会在控制台输出,仅修改 nowtime 的值时没有输出:

useEffect(() => {    console.log('count', count);    console.log('nowtime', nowtime);}, [count]);

useEffect 的回调函数还可以返回一个函数,这个函数在 effect 生命周期结束之前调用。为防止内存泄漏,清除函数会在组件卸载前执行。另外,如果组件多次渲染,则在执行下一个 effect 之前,上一个 effect 就已被清除。

基于上面的代码,我们稍微修改一下:

useEffect(() => {    console.log('count', count);    console.log('nowtime', nowtime);    return () => console.log('effect callback will be cleared');}, [count]);

怎么构建自己的react hooks

基于这个机制,在一些存在添加绑定和取消绑定的案例上特别合适,例如监听页面的窗口大小变化、设置定时器、与后端websocket 接口建立连接和断开连接等,都可以预计 useEffect 进行二次的封装,形成自定义的 hook。关于自定义 hook,下面我们会讲到。

1.3 useMemo 和 useCallback

function 组件中定义的变量和方法,在组件重新渲染时,都会重新重新进行计算,例如下面的这个例子:

const Home = () => {    const [count, setCount] = useState(0);    const [nowtime, setNowtime] = useState(0);    const getSum = () => {        const sum = ((1 + count) * count) / 2;        return sum + ' , ' + Math.random(); // 这个random是为了看到区别    };    return ( <>        <p> count: {count}< /p>        <p> sum: {getSum()}</p>        <p> nowtime: {nowtime}</p>        <button onClick = {() => setCount(count + 1)} > add 1 </button>        <button onClick = {() => setNowtime(Date.now())}> set now time </button>    </>);};

这里有 2 个按钮,一个是 count+1,一个设置当前的时间戳, getSun() 方法是计算从 1 到 count 的和,我们每次点击 add 按钮后,sum 方法都会重新计算和。可是当我们点击 settime 按钮时,getSum 方法也会重新计算,这是没有必要的。

这里我们可以使用 useMemo 来修改下:

const sum = useMemo(() => ((1 + count) * count) / 2 + ' , ' + Math.random(), [count]);<p> {sum} </p>;

修改后就可以看到,sum 的值只有在 count 发生变化的时候才重新计算,当点击 settime 按钮的时候,sum 并没有重新计算。这要得益于 useMemo 钩子的特性:

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

useMemo 返回回调里 return 的值,而且 memoizedValue 它仅会在某个依赖项改变时才重新计算。这种优化有助于避免在每次渲染时都进行高开销的计算。如果没有提供依赖项数组,useMemo 在每次渲染时都会计算新的值。

在上面的例子里,只有 count 变量发生变化时,才重新计算 sum,否则 sum 的值保持不变。

useCallback 与 useMemo 类型,只不过 useCallback 返回的是一个函数,例如:

const fn = useCallback(() => {    return ((1 + count) * count) / 2 + ' , ' + nowtime;}, [count]);

2. 实现几个自定义的 hook

在官方文档里,实现了好友的在线与离线功能。这里我们自己也学着实现几个 hook。

2.1 获取窗口变化的宽高

我们通过监听resize事件来获取实时获取window窗口的宽高,对这个方法进行封装后可以在生命周期结束前能自动解绑resize事件:

const useWinResize = () => {    const [size, setSize] = useState({        width: document.documentElement.clientWidth,        height: document.documentElement.clientHeight    });    const resize = useCallback(() => {        setSize({        width: document.documentElement.clientWidth,        height: document.documentElement.clientHeight    })    }, [])    useEffect(() => {        window.addEventListener('resize', resize);        return () => window.removeEventListener('resize', resize);    }, []);    return size;}

使用起来也非常方便:

const Home = () => {    const {width, height} = useWinResize();    return <div>        <p>width: {width}</p>        <p>height: {height}</p>    </div>;};

2.2 定时器 useInterval

前端中使用定时器时,通常要在组件生命周期结束前清除定时器,如果定时器的周期发生变化了,还要先清除定时器再重新按照新的周期来启动。这种最常用的场景就是九宫格抽奖,用户点击开始抽奖后,先缓慢启动,然后逐渐变快,接口返回中奖结果后,再开始减速,最后停止。

我们很容易想到用 useEffect 来实现这样的一个 hook:

const useInterval = (callback, delay) => {    useEffect(() => {        if (delay !== null) {            let id = setInterval(callback, delay);            return () => clearInterval(id);        }    }, [delay]);};

我们把这段代码用到项目中试试:

const Home = () => {    const [count, setCount] = useState(0);    useInterval(() => {        console.log(count);        setCount(count + 1);    }, 500);    return <div > {        count    } < /div>;};

可是这段运行后很奇怪,页面从 0 到 1 后,就再也不变了, console.log(count) 的输出表明代码并没有卡死,那么问题出在哪儿了?

React 组件中的 props 和 state 是可以改变的, React 会重渲染它们且「丢弃」任何关于上一次渲染的结果,它们之间不再有相关性。

useEffect() Hook 也「丢弃」上一次渲染结果,它会清除上一次 effect 再建立下一个 effect,下一个 effect 住新的 props 和 state,这也是我们第一次尝试简单示例可以正确工作的原因。

但 setInterval 不会「丢弃」。 它会一直引用老的 props 和 state 直到你把它换掉 —— 不重置时间你是无法做到的。

这里就要用到useRef这个 hook 了,我们把 callback 存储到 ref 中,当 callback 更新时去更新 ref.current 的值:

const useInterval = (callback, delay) => {    const saveCallback = useRef();    useEffect(() => {        // 每次渲染后,保存新的回调到我们的 ref 里        saveCallback.current = callback;    });    useEffect(() => {        function tick() {            saveCallback.current();        }        if (delay !== null) {            let id = setInterval(tick, delay);            return () => clearInterval(id);        }    }, [delay]);};

当我们使用新的 useInterval 时,发现就可以自增了

这里我们使用一个变量来控制增加的速度:

const [count, setCount] = useState(0);const [diff, setDiff] = useState(500);useInterval(() => {    setCount(count + 1);}, diff);return ( <div>    <p> count: {count} </p>    <p> diff: {diff}ms </p>     <p>        <button onClick = {() => setDiff(diff - 50)}> 加快50ms </button>         <button onClick = {() => setDiff(diff + 50)} > 减慢50ms </button>    </p></div>);

分别点击两个按钮,可以调整count增加的速度。

以上是“怎么构建自己的react hooks”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注编程网精选频道!

--结束END--

本文标题: 怎么构建自己的react hooks

本文链接: https://lsjlt.com/news/276738.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 怎么构建自己的react hooks
    这篇文章主要介绍怎么构建自己的react hooks,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1. 常用的一个 hooks官方中提供了几个内置的钩子,我们简单了解下他们的用法。1.1 useState: 状态钩子...
    99+
    2023-06-15
  • 详解如何构建自己的react hooks
    目录1. 常用的一个 hooks1.1 useState: 状态钩子1.2 useEffect: 副作用钩子1.3 useMemo 和 useCallback2. 实现几个自定义的 ...
    99+
    2024-04-02
  • 怎么在react中创建自定义hooks
    这篇文章主要介绍“怎么在react中创建自定义hooks”,在日常操作中,相信很多人在怎么在react中创建自定义hooks问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么在react中创建自定义hooks...
    99+
    2023-06-25
  • Linux中怎么构建自己的Wiki
    这篇文章主要为大家展示了“Linux中怎么构建自己的Wiki”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Linux中怎么构建自己的Wiki”这篇文章吧。Wiki是一种在网络上开放且可供多人协同...
    99+
    2023-06-28
  • 怎么构建一个自己的Laravel包
    这篇“怎么构建一个自己的Laravel包”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“怎么构建一个自己的Laravel包”文...
    99+
    2023-07-04
  • 教你在react中创建自定义hooks
    一、什么是自定义hooks 逻辑复用         简单来说就是使用自定义hook可以将某些组件逻辑提取到可重用的函数中。 自...
    99+
    2024-04-02
  • 自己构建mean framework
        由于项目的原因,项目的前端架构要从单纯的angularjs转到nodejs+angular+express的架构,这样的架构对大家来说可能比较眼熟,没错,就是大名鼎鼎的MEAN ...
    99+
    2024-04-02
  • 怎么构建自己的docker容器镜像
    本文小编为大家详细介绍“怎么构建自己的docker容器镜像”,内容详细,步骤清晰,细节处理妥当,希望这篇“怎么构建自己的docker容器镜像”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。一. 设置docker构建...
    99+
    2023-07-05
  • react怎么实现hooks
    这篇文章主要介绍“react怎么实现hooks”,在日常操作中,相信很多人在react怎么实现hooks问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”react怎么实现hoo...
    99+
    2024-04-02
  • 怎么创建自己的cssHook
    本篇内容主要讲解“怎么创建自己的cssHook”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么创建自己的cssHook”吧!   jQuery.cssHoo...
    99+
    2024-04-02
  • 如何使用自定义hooks对React组件进行重构
    这篇文章主要介绍了如何使用自定义hooks对React组件进行重构的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇如何使用自定义hooks对React组件进行重构文章都会有所收获,下面我们一起来看看吧。处理复杂性...
    99+
    2023-07-05
  • 怎么学习React Hooks原理
    这篇文章主要介绍“怎么学习React Hooks原理”,在日常操作中,相信很多人在怎么学习React Hooks原理问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么学习Re...
    99+
    2024-04-02
  • 怎么在React中使用Hooks
    这篇文章给大家介绍怎么在React中使用Hooks,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。一、State Hook1、基础用法function State(){  const&nbs...
    99+
    2023-06-14
  • hooks怎么在react中使用
    hooks怎么在react中使用?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。State Hooks案例:import { useState }&...
    99+
    2023-06-14
  • 怎么实现react拖拽hooks
    这篇文章主要介绍了怎么实现react拖拽hooks,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。前言源码总共也就一百多行,看完这个大致可以理解一些成熟的react拖拽库的实现...
    99+
    2023-06-14
  • 怎么在云服务器上构建自己的网站
    在云服务器上构建自己的网站,你需要按照以下步骤进行操作:1. 选择云服务提供商:首先选择一个云服务提供商,确保选择一个可靠且适合你需...
    99+
    2023-09-28
    云服务器
  • 怎么使用python构建一个自己的聊天室
    今天小编给大家分享一下怎么使用python构建一个自己的聊天室的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一、网络编程基础...
    99+
    2023-07-05
  • React Hooks与setInterval的坑怎么解决
    这篇文章主要讲解了“React Hooks与setInterval的坑怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“React Hooks与setInterval...
    99+
    2023-06-30
  • 如何创建自己的第一个React 页面
    目录Rract是啥?背景 React脚手架JSX是什么Rract是啥? React 是用于构建用户界面的 JavaScript 库 构建用户界面. User Interfa...
    99+
    2024-04-02
  • React Hooks的原理是什么
    这篇文章主要讲解了“React Hooks的原理是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“React Hooks的原理是什么”吧!0x0...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作