15 个很有用的自定义 React Hooks

可莉
• 阅读 968

React 提供了自定义 Hooks 的特性,我们可以根据这个特性创建出很多有意思的功能,今天就来分享一些个人认为还不错的 Hooks,共计 15 个。

如果对于 React Hooks 还不是特别熟悉的话,可以先参阅这篇文章:React Hooks 温故而知新

useClippy

useClippy 是一个用来读取或写入粘贴板的自定义 Hook,支持 TypeScript。

官方文档:https://github.com/CharlesStover/use-clippy

代码示例:

import useClippy from 'use-clippy';export default () => {  const [clipboard, setClipboard] = useClippy();  return (    <div>      <button        onClick={() => {          alert(`粘贴板内容为: ${clipboard}`);        }}      >        读取粘贴板      </button>      <button        onClick={() => {          setClipboard(`新内容: ${Math.random()}`);        }}      >        写入粘贴板      </button>    </div>  );};

useWindowSize

useWindowSize 用于获取浏览器窗口大小,默认按 debounce 方式获取,当然也可以以 throttled 方式获取。

官方文档:https://github.com/jaredLunde/react-hook/tree/master/packages/window-size

代码示例:

import { useWindowSize } from '@react-hook/window-size';// import { useWindowSize } from '@react-hook/window-size/throttled';export default (props) => {  const [width, height] = useWindowSize();  return (    <div>      width: {width}, height: {height}    </div>  );};

useMediaQuery

useMediaQuery通过在组件中使用 CSS3 Media Query 来控制组件。

官方文档:https://github.com/jaredLunde/react-hook/tree/master/packages/media-query

代码示例:

import React from 'react';import { useMediaQuery, useMediaQueries } from '@react-hook/media-query';// Using a single media query// export default () => {//   const matches = useMediaQuery('only screen and (min-width: 400px)');//   return `Matches? ${matches ? 'Matched!' : 'Nope'}`;// };// Using multiple media queriesexport default () => {  const { matches, matchesAny, matchesAll } = useMediaQueries({    screen: 'screen',    width: '(min-width: 400px)',  });  return (    <ul>      <li>Screen matched? {matches.screen ? 'Yes' : 'No'}</li>      <li>Width matched? {matches.width ? 'Yes' : 'No'}</li>      <li>All matched? {matchesAll ? 'Yes' : 'No'}</li>      <li>Any matched? {matchesAny ? 'Yes' : 'No'}</li>    </ul>  );};

useAsync

useAsync 用于优雅地解决、取消和处理异步函数或 Promise,并且当组件卸载时还可以自动清除它们。

官方文档:https://github.com/jaredLunde/react-hook/tree/master/packages/async

代码示例:

import { useAsync } from '@react-hook/async';export default () => {  const [{ status, cancel, error, value }, call] = useAsync(() => {    return new Promise((resolve) => setTimeout(() => resolve('Loaded'), 3000));  });  switch (status) {    case 'loading':      return (        <div>          <button onClick={cancel}>Cancel</button>          Loading...        </div>      );    case 'cancelled':      return (        <div>          Cancelled.          <button onClick={call}>Try again</button>        </div>      );    case 'error':      return `Error: ${error}`;    case 'success':      return value || 'Success!';    default:      return <button onClick={call}>Load me</button>;  }};

useBrowserContextCommunication

useBrowserContextCommunication 使用 Broadcast Channel API  为不同浏览器上下文(选项卡,iframe,窗口)之间的通信提供简单的解决方案。

官方文档:https://github.com/AvraamMavridis/react-window-communication-hook

代码示例:

import useBrowserContextCommunication from 'react-window-communication-hook';export default () => {  // communicationState 是一个 {lastMessage, messages} 对象,用于从其它的浏览器上下文接收数据  const [communicationState, postMessage] = useBrowserContextCommunication(    'channel'  );  const [status, setStatus] = useState('login');  function logout() {    setStatus('logout');    postMessage('logout');  }  const isLogout = [communicationState.lastMessage, status].includes('logout');  return (    <div>      <h1>状态:{isLogout ? '已退出' : '已登录'}</h1>      <button onClick={logout}>退出</button>    </div>  );};

可以在浏览器里打开两个 Tab,然后在其中一个页面点击「退出」按钮,会发现两个 Tab 的页面都发生了变化。

useScript

useScript 用于动态加载外部脚本,并提供了 onLoad 回调用于得到脚本加载完成的时间。

官方文档:https://github.com/hupe1980/react-script-hook

代码示例:

import { StripeProvider } from 'react-stripe-elements';import useScript from 'react-script-hook';export default () => {  const [loading, error] = useScript({ src: 'https://js.stripe.com/v3/' });  if (loading) return <h3>Loading Stripe API...</h3>;  if (error) return <h3>Failed to load Stripe API: {error.message}</h3>;  return (    <StripeProvider apiKey="pk_test_6pRNASCoBOKtIshFeQd4XMUh">      <div>Hello</div>    </StripeProvider>  );};

当然也可以以回调函数的形式使用:

useScript({   src: 'https://js.stripe.com/v3/',  onload: () => console.log('Script loaded!') })

useLocalStorage

useLocalStorage 用于通过 localStorage API  进行数据存取。

官方文档:https://github.com/rehooks/local-storage

代码示例:

import { useLocalStorage, writeStorage } from '@rehooks/local-storage';let counter = 0;export default () => {  const [counterData] = useLocalStorage('counter');  return (    <>      {counter}      <button onClick={() => writeStorage('counter', ++counter)}>Write</button>      <button onClick={() => alert(counterData)}>Read</button>    </>  );};

useIdb

useIdb 使用浏览器中的 IndexedDB 来存储数据,跟 useLocalStorage 类似。

官方文档:https://github.com/kigiri/react-use-idb

代码示例:

import { useIdb } from 'react-use-idb';export default () => {  const [value, setValue] = useIdb('my-key', 'foo');  return (    <div>      <div>Value: {value}</div>      <button onClick={() => setValue('bar')}>bar</button>      <button onClick={() => setValue('baz')}>baz</button>    </div>  );};

use-mouse-action

use-mouse-action 用于监听点击事件时鼠标(也可能是触摸板)按下或弹起。

官方文档:https://github.com/dimitrinicolas/use-mouse-action

代码示例:

import useMouseAction from 'use-mouse-action';export default () => {  const props = useMouseAction({    onAction: () => console.log('You clicked or mouse downed me!'),    down: true,  });  return (    <button type="button" {...props}>      Click me fast!    </button>  );};

useDebounce

useDebounce 用于延迟 setState 或者其它回调函数的执行。

官方文档:https://github.com/jaredLunde/react-hook/tree/master/packages/debounce

代码示例:

import {useDebounce, useDebounceCallback} from '@react-hook/debounce'const Component = (props) => {  // at a basic level, used just like useState  const [value, setValue] = useDebounce('initialValue')}const useMyCallback = (initialState, wait, leading) => {  // this is the same code useDebounce() uses to debounce setState  const [state, setState] = useState(initialState)  return [state, useDebounceCallback(setState, wait, leading)]}

useThrottle

useThrottle 用于稀释 setState 或者其它回调函数的执行频率。

官方文档:https://github.com/jaredLunde/react-hook/tree/master/packages/throttle

代码示例:

import {useThrottle, useThrottleCallback} from '@react-hook/throttle'const Component = (props) => {  // at a basic level, used just like useState  const [value, setValue] = useThrottle('initialValue')}const useMyCallback = (initialState, fps, leading) => {  // this is the same code useThrottle() uses to throttle setState  const [state, setState] = useState(initialState)  return [state, useThrottleCallback(setState, fps, leading)]}

useOnlineStatus

useOnlineStatus 用于获取当前的网络状态,内部通过监听 onlineoffline 事件实现。

官方文档:https://github.com/rehooks/online-status

代码示例:

import useOnlineStatus from '@rehooks/online-status';export default () => {  const onlineStatus = useOnlineStatus();  return (    <div>      <h1>You are {onlineStatus ? 'Online' : 'Offline'}</h1>    </div>  );};

useDocumentTitle

useDocumentTitle 用于更新页面标题。

官方文档:https://github.com/rehooks/document-title

代码示例:

import useDocumentTitle from '@rehooks/document-title';export default () => {  useDocumentTitle('Page Title');  return <div />;};

useNetworkStatus

useNetworkStatus 暴露了navigator.connection 对象,用于实时获取网络状态。

官方文档:https://github.com/rehooks/network-status/

代码示例:

import useNetworkStatus from '@rehooks/network-status';export default () => {  let connection = useNetworkStatus();  return (    <div>      <div>downlink: {connection.downlink}</div>      <div>effectiveType: {connection.effectiveType}</div>      <div>rtt: {connection.rtt}</div>      <div>saveData: {connection.saveData ? 'yes' : 'no'}</div>    </div>  );};

useSpeechSynthesis

useSpeechSynthesis 通过使用 Web Speech API 提供了语音识别及文字转语音的能力,还可以识别中英文。

官方文档:https://www.npmjs.com/package/react-speech-kit

在线示例:https://mikeyparton.github.io/react-speech-kit/

代码示例:

import { useSpeechSynthesis, useSpeechRecognition } from 'react-speech-kit';export default () => {  const [value, setValue] = useState('');  const { speak } = useSpeechSynthesis();  const { listen, listening, stop } = useSpeechRecognition({    onResult: (result) => {      setValue(result);    },  });  return (    <div>      <textarea        value={value}        onChange={(event) => setValue(event.target.value)}      />      <br />      <button onMouseDown={listen} onMouseUp={stop}>        Listen      </button>      <button onClick={() => speak({ text: value })}>Speak</button>      {listening && <div>Go ahead I'm listening</div>}    </div>  );};

可以按住 Listen 按钮不放随便说一句话,它会自动识别录入到文本框里,然后再点击Speak 按钮,它会自动识别文本框中的内容并语音播放。

支持

欢迎关注「前端瓶子君」,回复「交流」加入前端交流群!

欢迎关注「前端瓶子君」,回复「算法」自动加入,从0到1构建完整的数据结构与算法体系!

在这里,瓶子君不仅介绍算法,还将算法与前端各个领域进行结合,包括浏览器、HTTP、V8、React、Vue源码等。

在这里,你可以每天学习一道大厂算法题(阿里、腾讯、百度、字节等等)或 leetcode,瓶子君都会在第二天解答哟!

15 个很有用的自定义 React Hooks

》》面试官也在看的算法资料《《

“在看和转发” 就是最大的支持

本文分享自微信公众号 - 前端瓶子君(pinzi_com)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这