你应该会喜欢的5个自定义 Hook,Dubbo高频面试题+解析

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Web前端全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024c (备注前端)
img

正文

setError(error);

setData(null);

}

});

}, [url, options]);

};

export default useFetch;

useFetch返回一个对象,其中包含从URL中获取的数据,如果发生了任何错误,则返回错误。

return { error, data };

最后,向用户表明异步请求的状态通常是一个好做法,比如在呈现结果之前显示 loading。

因此,我们添加第三个 state 变量来跟踪请求的状态。在请求之前,将loading设置为true,并在请求之后完成后设置为false

const useFetch = (url = ‘’, options = null) => {

const [data, setData] = useState(null);

const [error, setError] = useState(null);

const [loading, setLoading] = useState(false);

useEffect(() => {

setLoading(true);

fetch(url, options)

.then(res => res.json())

.then(data => {

setData(data);

setError(null);

})

.catch(error => {

setError(error);

setData(null);

})

.finally(() => setLoading(false));

}, [url, options]);

return { error, data };

};

现在,我们可以返回 loading 变量,以便在请求运行时在组件中使用它来呈现一个 loading,方便用户知道我们正在获取他们所请求的数据。

return { loading, error, data };

在使用 userFetch 之前,我们还有一件事。

我们需要检查使用我们 Hook 的组件是否仍然被挂载,以更新我们的状态变量。否则,会有内存泄漏。

import { useState, useEffect } from ‘react’;

const useFetch = (url = ‘’, options = null) => {

const [data, setData] = useState(null);

const [error, setError] = useState(null);

const [loading, setLoading] = useState(false);

useEffect(() => {

let isMounted = true;

setLoading(true);

fetch(url, options)

.then(res => res.json())

.then(data => {

if (isMounted) {

setData(data);

setError(null);

}

})

.catch(error => {

if (isMounted) {

setError(error);

setData(null);

}

})

.finally(() => isMounted && setLoading(false));

return () => (isMounted = false);

}, [url, options]);

return { loading, error, data };

};

export default useFetch;

接下就是怎么用了?

我们只需要传递我们想要检索的资源的URL。从那里,我们得到一个对象,我们可以使用它来渲染我们的应用程序。

import useFetch from ‘./useFetch’;

const App = () => {

const { loading, error, data = [] } = useFetch(

‘https://hn.algolia.com/api/v1/search?query=react’

);

if (error) return

Error!

;

if (loading) return

Loading…

;

return (

    {data?.hits?.map(item => (

    • {item.title}

      ))}

      );

      };

      useEventListener

      这个 Hook 负责在组件内部设置和清理事件监听器。

      这样,我们就不需要每次添加事件监听器,做重复的工作。

      这个函数有几个参数,eventType 事件类型,listener 监听函数,target 监听对象,options 可选参数。

      import { useEffect, useRef } from ‘react’;

      const useEventListener = (

      eventType = ‘’,

      listener = () => null,

      target = null,

      options = null

      ) => {};

      export default useEventListener;

      与前一个 Hook 一样,用 useEffect 来添加一个事件监听器。首先,我们需要确保target 是否支持addEventListener方法。否则,我们什么也不做。

      import { useEffect, useRef } from ‘react’;

      const useEventListener = (

      eventType = ‘’,

      listener = () => null,

      target = null,

      options = null

      ) => {

      useEffect(() => {

      if (!target?.addEventListener) return;

      }, [target]);

      };

      export default useEventListener;

      然后,我们可以添加实际的事件监听器并在卸载函数中删除它。

      import { useEffect, useRef } from ‘react’;

      const useEventListener = (

      eventType = ‘’,

      listener = () => null,

      target = null,

      options = null

      ) => {

      useEffect(() => {

      if (!target?.addEventListener) return;

      target.addEventListener(eventType, listener, options);

      return () => {

      target.removeEventListener(eventType, listener, options);

      };

      }, [eventType, target, options, listener]);

      };

      export default useEventListener;

      实际上,我们也会使用一个引用对象来存储和持久化监听器函数。只有当监听器函数发生变化并在事件监听器方法中使用该引用时,我们才会更新该引用。

      import { useEffect, useRef } from ‘react’;

      const useEventListener = (

      eventType = ‘’,

      listener = () => null,

      target = null,

      options = null

      ) => {

      const savedListener = useRef();

      useEffect(() => {

      savedListener.current = listener;

      }, [listener]);

      useEffect(() => {

      if (!target?.addEventListener) return;

      const eventListener = event => savedListener.current(event);

      target.addEventListener(eventType, eventListener, options);

      return () => {

      target.removeEventListener(eventType, eventListener, options);

      };

      }, [eventType, target, options]);

      };

      export default useEventListener;

      我们不需要从此 Hook 返回任何内容,因为我们只是侦听事件并运行处理程序函数传入作为参数。

      现在,很容易将事件侦听器添加到我们的组件(例如以下组件)中,以检测DOM元素外部的点击。 如果用户单击对话框组件,则在此处关闭对话框组件。

      import { useRef } from ‘react’;

      import ReactDOM from ‘react-dom’;

      import { useEventListener } from ‘./hooks’;

      const Dialog = ({ show = false, onClose = () => null }) => {

      const dialogRef = useRef();

      // Event listener to close dialog on click outside element

      useEventListener(

      ‘mousedown’,

      event => {

      if (event.defaultPrevented) {

      return; // Do nothing if the event was already processed

      }

      if (dialogRef.current && !dialogRef.current.contains(event.target)) {

      console.log(‘Click outside detected -> closing dialog…’);

      onClose();

      }

      },

      window

      );

      return show

      ? ReactDOM.createPortal(

      className=“relative bg-white rounded-md shadow-card max-h-full max-w-screen-sm w-full animate-zoom-in px-6 py-20”

      ref={dialogRef}

      What’s up{’ '}

      YouTube

      ?

      ,

      document.body

      )
      null;

      };

      export default Dialog;

      useLocalStorage

      这个 Hook 主要有两个参数,一个是 key,一个是 value

      import { useState } from ‘react’;

      const useLocalStorage = (key = ‘’, initialValue = ‘’) => {};

      export default useLocalStorage;

      然后,返回一个数组,类似于使用 useState 获得的数组。 因此,此数组将包含有状态值和在将其持久存储在localStorage 中时对其进行更新的函数。

      首先,我们创建将与 localStorage 同步的React状态变量。

      import { useState } from ‘react’;

      const useLocalStorage = (key = ‘’, initialValue = ‘’) => {

      const [state, setState] = useState(() => {

      try {

      const item = window.localStorage.getItem(key);

      return item ? JSON.parse(item) : initialValue;

      } catch (error) {

      console.log(error);

      return initialValue;

      }

      });

      };

      export default useLocalStorage;

      在这里,我们使用惰性初始化来读取 localStorage 以获取键的值,如果找到该值,则解析该值,否则返回传入的initialValue

      如果在读取 localStorage 时出现错误,我们只记录一个错误并返回初始值。

      最后,我们需要创建 update 函数来返回它将在localStorage 中存储任何状态的更新,而不是使用useState 返回的默认更新。

      import { useState } from ‘react’;

      const useLocalStorage = (key = ‘’, initialValue = ‘’) => {

      const [state, setState] = useState(() => {

      try {

      const item = window.localStorage.getItem(key);

      return item ? JSON.parse(item) : initialValue;

      } catch (error) {

      return initialValue;

      }

      });

      const setLocalStorageState = newState => {

      try {

      const newStateValue =

      typeof newState === ‘function’ ? newState(state) : newState;

      setState(newStateValue);

      window.localStorage.setItem(key, JSON.stringify(newStateValue));

      } catch (error) {

      console.error(Unable to store new value for ${key} in localStorage.);

      }

      };

      return [state, setLocalStorageState];

      };

      export default useLocalStorage;

      此函数同时更新React状态和 localStorage 中的相应键/值。 这里,我们还可以支持函数更新,例如常规的useState hook。

      最后,我们返回状态值和我们的自定义更新函数。

      现在可以使用useLocalStorage hook 将组件中的任何数据持久化到localStorage中。

      import { useLocalStorage } from ‘./hooks’;

      const defaultSettings = {

      notifications: ‘weekly’,

      };

      function App() {

      const [appSettings, setAppSettings] = useLocalStorage(

      ‘app-settings’,

      defaultSettings

      );

      return (

      Your application's settings:

      <select

      value={appSettings.notifications}

      onChange={e =>

      setAppSettings(settings => ({

      …settings,

      notifications: e.target.value,

      }))

      }

      className="border border-gray-900 rounded py-2 px-4 "

      daily weekly monthly

      <button

      onClick={() => setAppSettings(defaultSettings)}

      className=“rounded-md shadow-md py-2 px-6 bg-red-500 text-white uppercase font-medium tracking-wide text-sm leading-8”

      Reset settings

      );

      }

      export default App;

      useMediaQuery

      这个 Hook 帮助我们在功能组件中以编程方式测试和监控媒体查询。这是非常有用的,例如,当你需要渲染不同的UI取决于设备的类型或特定的特征。

      我们的 Hook 接受3个参数:

      • 首先,对应媒体查询的字符串数组

      • 然后,以与前一个数组相同的顺序匹配这些媒体查询的值数组

      • 最后,如果没有匹配的媒体查询,则使用默认值

      紧跟潮流

      大前端和全栈是以后前端的一个趋势,懂后端的前端,懂各端的前端更加具有竞争力,以后可以往这个方向靠拢。

      这边整理了一个对标“阿里 50W”年薪企业高级前端工程师成长路线,由于图片太大仅展示一小部分

      网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

      需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)
      img

      一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
      adow-md py-2 px-6 bg-red-500 text-white uppercase font-medium tracking-wide text-sm leading-8"

      Reset settings

      );

      }

      export default App;

      useMediaQuery

      这个 Hook 帮助我们在功能组件中以编程方式测试和监控媒体查询。这是非常有用的,例如,当你需要渲染不同的UI取决于设备的类型或特定的特征。

      我们的 Hook 接受3个参数:

      • 首先,对应媒体查询的字符串数组

      • 然后,以与前一个数组相同的顺序匹配这些媒体查询的值数组

      • 最后,如果没有匹配的媒体查询,则使用默认值

      紧跟潮流

      大前端和全栈是以后前端的一个趋势,懂后端的前端,懂各端的前端更加具有竞争力,以后可以往这个方向靠拢。

      这边整理了一个对标“阿里 50W”年薪企业高级前端工程师成长路线,由于图片太大仅展示一小部分

      网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

      需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)
      [外链图片转存中…(img-HO9egEGH-1713230939330)]

      一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

    • 13
      点赞
    • 27
      收藏
      觉得还不错? 一键收藏
    • 0
      评论
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值