Giter VIP home page Giter VIP logo

usehooks-ts's Introduction

usehooks-ts banner


usehooks-ts

React hook library, ready to use, written in Typescript.

Contributor Covenant NPM Downloads NPM Downloads License npm bundle size npm All Contributors


npm i usehooks-ts

Created by Julien Caron and maintained with ❀️ by an amazing team of developers.

πŸ’« Introduction

useHooks(πŸ”₯).ts is a React hooks library, written in Typescript and easy to use. It provides a set of hooks that enables you to build your React applications faster. The hooks are built upon the principles of DRY (Don't Repeat Yourself). There are hooks for most common use cases you might need.

The library is designed to be as minimal as possible. It is fully tree-shakable (using the ESM version), meaning that you only import the hooks you need, and the rest will be removed from your bundle making the cost of using this library negligible. Most hooks are extensively tested and are being used in production environments.

Usage example

import { useLocalStorage } from 'usehooks-ts'

function Component() {
  const [value, setValue] = useLocalStorage('my-localStorage-key', 0)

  // ...
}

πŸͺ Available Hooks

πŸ’š Backers

Big thanks go to all our backers! [Become a backer]

Sentry
Sentry
KATT
KATT
Adhi Ravishankar
Adhi Ravishankar
great-work-told-is
great-work-told-is

✨ Contributors

Big thanks go to all our contributors! [Become a contributor]

Julien
Julien

πŸ–‹ πŸ’» 🎨 πŸ€”
a777med
a777med

πŸ’»
Nguyen Tien Dat
Nguyen Tien Dat

πŸ’»
Elias Cohenca
Elias Cohenca

πŸ–‹
JoΓ£o Deroldo
JoΓ£o Deroldo

πŸ› πŸ’»
Nishit
Nishit

πŸ’»
Jon Koops
Jon Koops

πŸ’»
LoneRifle
LoneRifle

πŸ’»
Viktor
Viktor

πŸ€” πŸ›
Bruno Clermont
Bruno Clermont

πŸ’¬
yoannesbourg
yoannesbourg

πŸ€”
Strange2x
Strange2x

πŸ€”
Jason Pickens
Jason Pickens

πŸ›
Sel-Vin Kuik
Sel-Vin Kuik

πŸ›
isaac
isaac

πŸ›
Bruno RZN
Bruno RZN

πŸ’» πŸ‘€
Nathan Manceaux-Panot
Nathan Manceaux-Panot

πŸ’» πŸ‘€
Dien Vu
Dien Vu

πŸ€”
Oleg Kusov
Oleg Kusov

πŸ€”
Matthew Guy
Matthew Guy

πŸ€”
andrewbihl
andrewbihl

πŸ›
lancepollard
lancepollard

πŸ›
Mukul Bansal
Mukul Bansal

πŸ›
Jean-Luc Mongrain sur la Brosse
Jean-Luc Mongrain sur la Brosse

πŸ’» πŸ€”
Nic
Nic

πŸ–‹
Dan Wood
Dan Wood

πŸ’»
jo wendenbuerger
jo wendenbuerger

πŸ›
Andrew Nosenko
Andrew Nosenko

πŸ›
CharlieJhonSmith
CharlieJhonSmith

πŸ’»
Sullivan SENECHAL
Sullivan SENECHAL

πŸ€” πŸ› πŸ’»
Jason Long
Jason Long

πŸ›
kxm766
kxm766

πŸ›
Quentin
Quentin

πŸ’» πŸ€” πŸ–‹
Daniel Lazar
Daniel Lazar

πŸ’» πŸ›
Mark Terrel
Mark Terrel

πŸ› πŸ’»
Andreas Herd
Andreas Herd

πŸ›
Sonjoy Datta
Sonjoy Datta

πŸ’»
Ilya Belsky
Ilya Belsky

πŸ›
James Barrett
James Barrett

πŸ’»
AbbalYouness
AbbalYouness

πŸ’»
didriklind
didriklind

πŸ’» ⚠️
hexp1989
hexp1989

πŸ’»
Alvaro Serrano
Alvaro Serrano

πŸ–‹
Egehan DΓΌlger
Egehan DΓΌlger

πŸ’»
PabloLION
PabloLION

πŸ› πŸ’»
David Sanchez
David Sanchez

πŸ›
Ajay Raja
Ajay Raja

πŸ›
Andy Merskin
Andy Merskin

πŸ€”
Avirup Ghosh
Avirup Ghosh

πŸ’» πŸ›
Sanne WintrΓ©n
Sanne WintrΓ©n

πŸ›
Alessandro
Alessandro

πŸ›
Andrey Tatarenko
Andrey Tatarenko

πŸ›
Anton Rusak
Anton Rusak

πŸ›
Mahmood Bagheri
Mahmood Bagheri

πŸ’»
Anver Sadutt
Anver Sadutt

πŸ–‹
Bogdan Ailincai
Bogdan Ailincai

πŸ’»
Simeon Griggs
Simeon Griggs

πŸ›
Kepro
Kepro

πŸ›
Jake Lippert
Jake Lippert

πŸ›
Tu Nguyen Anh
Tu Nguyen Anh

πŸ› πŸ’»
Luke Shiels
Luke Shiels

πŸ›
Sergei Kolyago
Sergei Kolyago

πŸ€”
Adham Akmal Azmi
Adham Akmal Azmi

πŸ›
Alek Kowalczyk
Alek Kowalczyk

πŸ›
Sean Callahan
Sean Callahan

πŸ›
Joshua Bean
Joshua Bean

πŸ’» πŸ›
Tim Zhao
Tim Zhao

πŸ›
Patrick
Patrick

πŸ›
Bryce Dorn
Bryce Dorn

πŸ’»
angusd3v
angusd3v

πŸ’»
Davide Di Simone
Davide Di Simone

πŸ›
Jack Herrington
Jack Herrington

πŸ›
Avi Sharvit
Avi Sharvit

πŸ’» πŸ›
Nicolae Maties
Nicolae Maties

πŸ›
Shardul Aeer
Shardul Aeer

πŸ›
Herlon Aguiar
Herlon Aguiar

πŸ›
Alexis Oney
Alexis Oney

πŸ–‹
curtvict
curtvict

πŸ’»
JosuΓ© Cortina
JosuΓ© Cortina

πŸ–‹
Alex / KATT
Alex / KATT

πŸ’»
Mourad EL CADI
Mourad EL CADI

πŸ’» πŸ›
James Hulena
James Hulena

πŸ›
Matthew Hailwood
Matthew Hailwood

πŸ’» πŸ‘€
Michael Norrie
Michael Norrie

πŸ›
Valentin Politov
Valentin Politov

πŸ’»
Marnus Weststrate
Marnus Weststrate

πŸ’»
mancuoj
mancuoj

πŸ–‹
Chat Sumlin
Chat Sumlin

πŸ’»
Owen Haupt
Owen Haupt

πŸ› πŸ–‹
ubarbaxor
ubarbaxor

πŸ’»
Michael Mior
Michael Mior

πŸ› πŸ–‹
Pierre
Pierre

πŸ’»
Harry B
Harry B

πŸ›
Valerie
Valerie

πŸ› πŸ’»
Steven Vachon
Steven Vachon

πŸ’»
Sean Kirby
Sean Kirby

⚠️ πŸ’»
Alecsander Farias
Alecsander Farias

πŸ’»
Rahul Mishra
Rahul Mishra

πŸ’» πŸ‘€ πŸ–‹
Bryant Smith
Bryant Smith

πŸ’» πŸ›
Rob Hannay
Rob Hannay

πŸ’»
Hooriza
Hooriza

πŸ’» πŸ›
ShanSenanayake
ShanSenanayake

πŸ’»
Philip Ghering
Philip Ghering

πŸ’»
Ladislas Dellinger
Ladislas Dellinger

πŸ’»
Haff
Haff

πŸ’»
Lisandro
Lisandro

πŸ’»
Amir hossein rezaei
Amir hossein rezaei

πŸ’»
Nicolas Macian
Nicolas Macian

πŸ› πŸ’»
Nate Forsyth
Nate Forsyth

πŸ’»
satelllte
satelllte

πŸ’» πŸ›
Federico Panico
Federico Panico

πŸ’»
William Pei Yuan
William Pei Yuan

πŸ’»
Mihai
Mihai

πŸ’» πŸ›
Habib Ogunsola
Habib Ogunsola

πŸ–‹
Ash Furrow
Ash Furrow

πŸ’»
Daniel TuruΘ™
Daniel TuruΘ™

πŸ’»
Rahul Chaudhary
Rahul Chaudhary

πŸ–‹ πŸ›
Joshua Ojoawo
Joshua Ojoawo

πŸ€” πŸ›
Jack
Jack

πŸ’»
Jon Linkens
Jon Linkens

πŸ’» πŸ›
Jeongjin Oh
Jeongjin Oh

πŸ›
Tianning Li
Tianning Li

πŸ’»
Lars Artmann
Lars Artmann

πŸ–‹
KBobovskiy
KBobovskiy

πŸ’»
✨ Kathryn Gonzalez ✨
✨ Kathryn Gonzalez ✨

πŸ–‹
Yaroslav Chapelskyi
Yaroslav Chapelskyi

πŸ–‹
Samuel Van Erps
Samuel Van Erps

πŸ‘€
ojolowoblue
ojolowoblue

πŸ–‹
Andrii Kostenko
Andrii Kostenko

πŸ’»
Akeem Allen
Akeem Allen

πŸ’» πŸ›
trongbinhnguyen
trongbinhnguyen

πŸ–‹
Aniruddha Sil
Aniruddha Sil

πŸ’»
λ°•μ°¬ν˜
λ°•μ°¬ν˜

πŸ‘€
Anish
Anish

πŸ’»
Hugo Hutri
Hugo Hutri

πŸ–‹
Balz Guenat
Balz Guenat

πŸ’»
OtterGeorge
OtterGeorge

πŸ’»
Samay Sagar
Samay Sagar

πŸ–‹
Pedro Lisboa
Pedro Lisboa

πŸ›
Henrique Malheiros
Henrique Malheiros

πŸ›
Kevin Newman
Kevin Newman

πŸ’»
a503189
a503189

πŸ–‹
Mourad EL CADI
Mourad EL CADI

πŸ’»
Pedro Henrique Lopes
Pedro Henrique Lopes

πŸ’»
Danbi Lee
Danbi Lee

πŸ’»
Connor Jennings
Connor Jennings

πŸ’»
Lucas Gomes
Lucas Gomes

πŸ› πŸ’»
Martin Zagora
Martin Zagora

πŸ’»
KvD
KvD

πŸ’»
Alex
Alex

πŸ’»
Kacey Cleveland
Kacey Cleveland

πŸ‘€
Avirup Ghosh
Avirup Ghosh

πŸ›
yabbal
yabbal

πŸ’»
Craig Patik
Craig Patik

πŸ›
Soldeplata Saketos Candela
Soldeplata Saketos Candela

πŸ’»
TENDOUZHI
TENDOUZHI

πŸ›
Marcin Wachulski
Marcin Wachulski

πŸ›
Salman Fazal
Salman Fazal

πŸ›
shrugs
shrugs

πŸ›
hyodori
hyodori

πŸ›
Eleazar β€œE” Ramos
Eleazar β€œE” Ramos

πŸ›
retnag
retnag

πŸ›
J young Lee
J young Lee

πŸ›
Filip Weiss
Filip Weiss

πŸ›
Marius Gundersen
Marius Gundersen

πŸ›
Syed Aman Ali
Syed Aman Ali

πŸ›
Axel Ingadi
Axel Ingadi

πŸ›
AndyP
AndyP

πŸ›
ishanVaghasiya
ishanVaghasiya

πŸ›
Nico Martinucci
Nico Martinucci

πŸ›
Shiv Bhonde | shivbhonde.eth
Shiv Bhonde | shivbhonde.eth

πŸ›
fritzmonkey
fritzmonkey

πŸ›
Rodrigo Mesquita
Rodrigo Mesquita

πŸ›
Moshe Simantov
Moshe Simantov

πŸ›
Beka
Beka

πŸ›
Abdallah Alkaser
Abdallah Alkaser

πŸ› πŸ’»
Carl Smith
Carl Smith

πŸ›
Orlando Groppo
Orlando Groppo

πŸ›
MartΔ³n Saly
MartΔ³n Saly

πŸ›
Quinn Shanahan
Quinn Shanahan

πŸ›
Antoine Kingue
Antoine Kingue

πŸ›
Ε½an Ε½lender
Ε½an Ε½lender

πŸ›
Sebastian Dominguez
Sebastian Dominguez

πŸ›
James Cowan
James Cowan

πŸ›
Bayram Ali Basgul
Bayram Ali Basgul

πŸ›
Wyatt Castaneda
Wyatt Castaneda

πŸ›
Tim Neville
Tim Neville

πŸ›
Thomas Pigarelli
Thomas Pigarelli

πŸ›
James Herdman
James Herdman

πŸ›
Grzegorz Pociejewski
Grzegorz Pociejewski

πŸ›
RenΓ© Verheij
RenΓ© Verheij

πŸ›
PatrykKuniczak
PatrykKuniczak

πŸ›
Paolo BoΕΎac
Paolo BoΕΎac

πŸ›
Rein
Rein

πŸ›
FloorianB
FloorianB

πŸ›
Xuan Hung
Xuan Hung

πŸ›
Monawwar Abdullah
Monawwar Abdullah

πŸ›
Haroldo de Oliveira Pinheiro
Haroldo de Oliveira Pinheiro

πŸ›
Tamjid Ahmed
Tamjid Ahmed

πŸ›
jv-lopez
jv-lopez

πŸ›
Callum Macrae
Callum Macrae

πŸ›
bywater529
bywater529

πŸ›
Kevin He
Kevin He

πŸ›
FredericoGauz
FredericoGauz

πŸ›
Jonathan "JonLem" Lemos
Jonathan "JonLem" Lemos

πŸ›
Xegulon
Xegulon

πŸ›
Tom Smedley
Tom Smedley

πŸ›
lightbluepoppy
lightbluepoppy

πŸ›
Derek Oware
Derek Oware

πŸ›
Lance Gliser
Lance Gliser

πŸ›
J. Lewis
J. Lewis

πŸ›
Yair
Yair

πŸ›
Nishchit
Nishchit

πŸ›
Devofy
Devofy

πŸ›
Josh Guyette
Josh Guyette

πŸ›
Dora Li
Dora Li

πŸ›
Kristian Gerardsson
Kristian Gerardsson

πŸ›
James Powell
James Powell

πŸ›
Boaz Poolman
Boaz Poolman

πŸ›
roker15
roker15

πŸ›
Fadhil Ahmad
Fadhil Ahmad

πŸ›
Chandler-Zhu
Chandler-Zhu

πŸ›
Nghi Nguyen
Nghi Nguyen

πŸ›
Shravan Sunder
Shravan Sunder

πŸ›
Johannes5
Johannes5

πŸ›
sebahhpeya
sebahhpeya

πŸ›
Or Nakash
Or Nakash

πŸ›
Erez Makavy
Erez Makavy

πŸ›
Andy Merskin
Andy Merskin

πŸ›
ChainAlert Bot
ChainAlert Bot

πŸ›
Taylor Morgan
Taylor Morgan

πŸ›
wisdomabioye
wisdomabioye

πŸ›
Samuel QuiΓ±ones
Samuel QuiΓ±ones

πŸ€”
Manuel
Manuel

πŸ’» πŸ›
Yurii Rybak
Yurii Rybak

πŸ›
Yury Demin
Yury Demin

πŸ› πŸ’»
Jon Tewksbury
Jon Tewksbury

πŸ’» πŸ›
Novac Denis
Novac Denis

πŸ’» πŸ›
kyrylo-soulandwolf
kyrylo-soulandwolf

πŸ’» πŸ›
Miguel Isidoro
Miguel Isidoro

πŸ’»
Yuriy Gromchenko
Yuriy Gromchenko

πŸ’»
Jacob Hummer
Jacob Hummer

πŸ€”
Kyrylo Melnychuk
Kyrylo Melnychuk

πŸ–‹ πŸ’»
Luma
Luma

πŸ’»
Eliya Cohen
Eliya Cohen

πŸ’»
Igor Sukharev
Igor Sukharev

πŸ›
pookmish
pookmish

πŸ€”
metav-drimz
metav-drimz

πŸ€”
luckrnx09
luckrnx09

πŸ’»
Hubert Kuczmierczyk
Hubert Kuczmierczyk

πŸ€” πŸ‘€
dandubya
dandubya

πŸ“–
Darwish
Darwish

πŸ’»
Jonathan Raoult
Jonathan Raoult

πŸ› πŸ‘€

This project follows the all-contributors specification (emoji key). Contributions of any kind welcome!

πŸ’ž Donate

If you find this piece of software helpful, please consider a donation. Any amount is greatly appreciated.

GitHub Sponsors Paypal Stripe Buy me a coffee

BTC: bc1qwys40tnd0lxf9lr9l0t6xc63dpxyucj4x4nay0

ETH: 0x36a85155a8300754C56395D5af24553FB18915D6

πŸ“ License

This project is MIT licensed.

usehooks-ts's People

Contributors

a777med avatar allcontributors[bot] avatar alvaroserrrano avatar amirking59 avatar blankparticle avatar bogdanailincaipnt avatar brycedorn avatar createdbymahmood avatar datkira avatar dependabot[bot] avatar egehandulger avatar hexp1989 avatar jontewks avatar juliencrn avatar k-melnychuk avatar lgxm3z avatar lonerifle avatar luckrnx09 avatar lumakernel avatar mancuoj avatar marnusw avatar n1c avatar nishit-dua avatar nmacianx avatar pablolion avatar qlaffont avatar renovate-bot avatar renovate[bot] avatar tuna-kai avatar ymc-maha avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

usehooks-ts's Issues

Can I PR new functions?

Hi team.
I made a ternary Darkmode (based on this repo) like "dark" | "system" | "light" in a project and I want to use it in another project.
The best way to share it is to upload it on NPM and GitHub. And I think putting it here might be helpful, as I see you have " Add new hooks" in your roadmap. Questions are:

  1. Is this too trivial to add?
  2. Can I make a PR on this repo?
  3. Do you have a Code of Conduct?

Thanks.

How to use useInterval but have the callback runRight away then on a delay

Was looking through this lib and it looks awesome. In a project on my team, we have a version of the useInterval hook from Dan's blog post, but we made a small modification to it. We added the ability for the callback to be executed right away.

function useInterval(callback, delay: number | null, runNow=false) {
  ...
  
  useEffect(() => {
    if (runNow && savedCallback.current) {
      savedCallback.current()
    } else return
  }, [runNow])
  
  ...
}

This has been useful for a handful of things. It seems like it would be generally useful, so I'm surprised that this isn't apart of the spec. But I'm guessing I'm just missing something simple with the useHooks-ts version to accomplish the same thing?

ChainAlert: npm package release (2.2.1) has no matching tag in this repo

Dear usehooks-ts maintainers,
Thank you for your contribution to the open-source community.

This issue was automatically created to inform you a new version (2.2.1) of usehooks-ts was published without a matching tag in this repo.

Our service monitors the open-source ecosystem and informs popular packages' owners in case of potentially harmful activity.
If you find this behavior legitimate, kindly close and ignore this issue. Read more

badge

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Awaiting Schedule

These updates are awaiting their schedule. Click on a checkbox to get an update now.

  • Update dependency rimraf to v6
  • Update dependency vitest to v2
  • Update turbo monorepo to v2 (major) (@turbo/gen, turbo)

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

github-actions
.github/workflows/ci.yml
  • actions/checkout v4
  • pnpm/action-setup v3
  • actions/setup-node v4
.github/workflows/update-algolia-index.yml
  • actions/checkout v4
  • pnpm/action-setup v3
  • actions/setup-node v4
npm
apps/www/package.json
  • @next/third-parties ^14.1.0
  • @radix-ui/react-dialog ^1.0.5
  • @radix-ui/react-dropdown-menu ^2.0.6
  • @radix-ui/react-slot ^1.0.2
  • @t3-oss/env-nextjs ^0.9.2
  • @types/voca ^1.4.1
  • algoliasearch ^4.22.1
  • class-variance-authority ^0.7.0
  • clsx ^2.1.0
  • cmdk ^1.0.0
  • date-fns ^3.3.1
  • gray-matter ^4.0.3
  • lucide-react ^0.364.0
  • next 14.1.4
  • next-mdx-remote ^4.4.1
  • react 18.2.0
  • react-dom 18.2.0
  • react-instantsearch ^7.6.0
  • rehype-prism-plus ^2.0.0
  • remark-gfm ^3.0.1
  • schema-dts ^1.1.2
  • tailwind-merge ^2.2.1
  • tailwindcss 3.4.3
  • tailwindcss-animate ^1.0.7
  • voca ^1.4.1
  • zod ^3.22.4
  • @tailwindcss/line-clamp ^0.4.4
  • @tailwindcss/typography ^0.5.10
  • @types/node 20.12.2
  • @types/react 18.2.73
  • @types/react-dom 18.2.23
  • autoprefixer 10.4.19
  • eslint-config-next 14.1.4
  • next-sitemap ^4.2.3
  • postcss 8.4.38
  • typescript 5.4.3
package.json
  • @changesets/cli ^2.27.1
  • @turbo/gen ^1.12.4
  • @t3-oss/env-core ^0.9.2
  • all-contributors-cli ^6.26.1
  • algoliasearch ^4.22.1
  • date-fns ^3.3.1
  • dotenv 16.4.5
  • eslint ^8.56.0
  • prettier ^3.2.5
  • rimraf ^5.0.5
  • turbo ^1.12.4
  • typedoc ^0.25.9
  • typedoc-plugin-markdown ^3.17.1
  • typedoc-plugin-mdn-links ^3.1.17
  • typedoc-plugin-missing-exports ^2.2.0
  • zod 3.22.4
  • zx ^7.2.3
  • node >=18.17.0
  • typescript ^5.3.3
packages/eslint-config-custom/package.json
  • @typescript-eslint/eslint-plugin ^7.0.2
  • @typescript-eslint/parser ^7.0.2
  • eslint-config-prettier ^9.1.0
  • eslint-plugin-import ^2.29.1
  • eslint-plugin-jsx-a11y ^6.8.0
  • eslint-plugin-prettier ^5.1.3
  • eslint-plugin-react ^7.33.2
  • eslint-plugin-react-hooks ^4.6.0
  • eslint-plugin-simple-import-sort ^12.0.0
  • eslint-plugin-vitest ^0.4.0
  • typescript ^5.3.3
packages/usehooks-ts/package.json
  • lodash.debounce ^4.0.8
  • @juggle/resize-observer ^3.4.0
  • @testing-library/jest-dom ^6.4.2
  • @testing-library/react ^14.2.1
  • @types/lodash.debounce ^4.0.9
  • @types/node ^20.11.19
  • @types/react 18.2.73
  • eslint-plugin-jsdoc ^48.1.0
  • eslint-plugin-tree-shaking ^1.12.1
  • jsdom ^24.0.0
  • react 18.2.0
  • tsup ^8.0.2
  • typescript ^5.3.3
  • vitest ^1.3.1
  • react ^16.8.0 || ^17 || ^18
  • node >=16.15.0

  • Check this box to trigger a request for Renovate to run again on this repository

I need a "appropriate loader"

Hello!

I'm using a create-react-app (react ^17.0.2) and a storybook (^6.3.4)
If I'm trying to use the useLocalStorage hook, my storybooks fails (all my development is done in the storybook).

I get this error:

ERROR in ./node_modules/usehooks-ts/dist/esm/useElementSize/useElementSize.js 11:23
Module parse failed: Unexpected token (11:23)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|     const handleSize = useCallback(() => {
|         setSize({
>             width: ref?.offsetWidth || 0,
|             height: ref?.offsetHeight || 0,
|         });
 @ ./node_modules/usehooks-ts/dist/esm/useElementSize/index.js 1:0-61 1:0-61 2:0-33 2:0-33
 @ ./node_modules/usehooks-ts/dist/esm/index.js
 @ ./src/layouts/notes/notes.tsx
 @ ./src/layouts/notes/notes.stories.js
 @ ./src sync ^\.(?:(?:^|\/|(?:(?:(?!(?:^|\/)\.).)*?)\/)(?!\.)(?=.)[^/]*?\.stories\.(js|jsx|ts|tsx))$
 @ ./generated-stories-entry.js
 @ multi ./node_modules/@pmmmwh/react-refresh-webpack-plugin/client/ReactRefreshEntry.js ./node_modules/@storybook/core-server/node_modules/@storybook/core-client/dist/esm/globals/polyfills.js ./node_modules/@storybook/core-server/node_modules/@storybook/core-client/dist/esm/globals/globals.js ./node_modules/webpack-hot-middleware/client.js?reload=true&quiet=false&noInfo=undefined ./node_modules/@pmmmwh/react-refresh-webpack-plugin/client/ErrorOverlayEntry.js ./storybook-init-framework-entry.js ./node_modules/@storybook/addon-docs/dist/esm/frameworks/common/config.js-generated-config-entry.js ./node_modules/@storybook/addon-docs/dist/esm/frameworks/react/config.js-generated-config-entry.js ./node_modules/@storybook/react/dist/esm/client/preview/config-generated-config-entry.js ./node_modules/@storybook/addon-links/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-actions/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-actions/dist/esm/preset/addArgs.js-generated-config-entry.js ./node_modules/@storybook/addon-backgrounds/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-backgrounds/dist/esm/preset/addParameter.js-generated-config-entry.js ./node_modules/@storybook/addon-measure/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-outline/dist/esm/preset/addDecorator.js-generated-config-entry.js ./.storybook/preview.js-generated-config-entry.js ./generated-stories-entry.js

ERROR in ./node_modules/usehooks-ts/dist/esm/useScript/useScript.js 17:23
Module parse failed: Unexpected token (17:23)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|             document.body.appendChild(script);
|             const setAttributeFromEvent = (event) => {
>                 script?.setAttribute('data-status', event.type === 'load' ? 'ready' : 'error');
|             };
|             script.addEventListener('load', setAttributeFromEvent);
 @ ./node_modules/usehooks-ts/dist/esm/useScript/index.js 1:0-51 1:0-51 2:0-28 2:0-28
 @ ./node_modules/usehooks-ts/dist/esm/index.js
 @ ./src/layouts/notes/notes.tsx
 @ ./src/layouts/notes/notes.stories.js
 @ ./src sync ^\.(?:(?:^|\/|(?:(?:(?!(?:^|\/)\.).)*?)\/)(?!\.)(?=.)[^/]*?\.stories\.(js|jsx|ts|tsx))$
 @ ./generated-stories-entry.js
 @ multi ./node_modules/@pmmmwh/react-refresh-webpack-plugin/client/ReactRefreshEntry.js ./node_modules/@storybook/core-server/node_modules/@storybook/core-client/dist/esm/globals/polyfills.js ./node_modules/@storybook/core-server/node_modules/@storybook/core-client/dist/esm/globals/globals.js ./node_modules/webpack-hot-middleware/client.js?reload=true&quiet=false&noInfo=undefined ./node_modules/@pmmmwh/react-refresh-webpack-plugin/client/ErrorOverlayEntry.js ./storybook-init-framework-entry.js ./node_modules/@storybook/addon-docs/dist/esm/frameworks/common/config.js-generated-config-entry.js ./node_modules/@storybook/addon-docs/dist/esm/frameworks/react/config.js-generated-config-entry.js ./node_modules/@storybook/react/dist/esm/client/preview/config-generated-config-entry.js ./node_modules/@storybook/addon-links/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-actions/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-actions/dist/esm/preset/addArgs.js-generated-config-entry.js ./node_modules/@storybook/addon-backgrounds/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-backgrounds/dist/esm/preset/addParameter.js-generated-config-entry.js ./node_modules/@storybook/addon-measure/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-outline/dist/esm/preset/addDecorator.js-generated-config-entry.js ./.storybook/preview.js-generated-config-entry.js ./generated-stories-entry.js

ERROR in ./node_modules/usehooks-ts/dist/esm/useLocalStorage/useLocalStorage.js 45:69
Module parse failed: Unexpected token (45:69)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| function parseJSON(value) {
|     try {
>         return value === 'undefined' ? undefined : JSON.parse(value ?? '');
|     }
|     catch (error) {
 @ ./node_modules/usehooks-ts/dist/esm/useLocalStorage/index.js 1:0-63 1:0-63 2:0-34 2:0-34
 @ ./node_modules/usehooks-ts/dist/esm/index.js
 @ ./src/layouts/notes/notes.tsx
 @ ./src/layouts/notes/notes.stories.js
 @ ./src sync ^\.(?:(?:^|\/|(?:(?:(?!(?:^|\/)\.).)*?)\/)(?!\.)(?=.)[^/]*?\.stories\.(js|jsx|ts|tsx))$
 @ ./generated-stories-entry.js
 @ multi ./node_modules/@pmmmwh/react-refresh-webpack-plugin/client/ReactRefreshEntry.js ./node_modules/@storybook/core-server/node_modules/@storybook/core-client/dist/esm/globals/polyfills.js ./node_modules/@storybook/core-server/node_modules/@storybook/core-client/dist/esm/globals/globals.js ./node_modules/webpack-hot-middleware/client.js?reload=true&quiet=false&noInfo=undefined ./node_modules/@pmmmwh/react-refresh-webpack-plugin/client/ErrorOverlayEntry.js ./storybook-init-framework-entry.js ./node_modules/@storybook/addon-docs/dist/esm/frameworks/common/config.js-generated-config-entry.js ./node_modules/@storybook/addon-docs/dist/esm/frameworks/react/config.js-generated-config-entry.js ./node_modules/@storybook/react/dist/esm/client/preview/config-generated-config-entry.js ./node_modules/@storybook/addon-links/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-actions/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-actions/dist/esm/preset/addArgs.js-generated-config-entry.js ./node_modules/@storybook/addon-backgrounds/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-backgrounds/dist/esm/preset/addParameter.js-generated-config-entry.js ./node_modules/@storybook/addon-measure/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-outline/dist/esm/preset/addDecorator.js-generated-config-entry.js ./.storybook/preview.js-generated-config-entry.js ./generated-stories-entry.js

ERROR in ./node_modules/usehooks-ts/dist/esm/useOnClickOutside/useOnClickOutside.js 4:23
Module parse failed: Unexpected token (4:23)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| function useOnClickOutside(ref, handler, mouseEvent = 'mousedown') {
|     useEventListener(mouseEvent, event => {
>         const el = ref?.current;
|         if (!el || el.contains(event.target)) {
|             return;
 @ ./node_modules/usehooks-ts/dist/esm/useOnClickOutside/index.js 1:0-67 1:0-67 2:0-36 2:0-36
 @ ./node_modules/usehooks-ts/dist/esm/index.js
 @ ./src/layouts/notes/notes.tsx
 @ ./src/layouts/notes/notes.stories.js
 @ ./src sync ^\.(?:(?:^|\/|(?:(?:(?!(?:^|\/)\.).)*?)\/)(?!\.)(?=.)[^/]*?\.stories\.(js|jsx|ts|tsx))$
 @ ./generated-stories-entry.js
 @ multi ./node_modules/@pmmmwh/react-refresh-webpack-plugin/client/ReactRefreshEntry.js ./node_modules/@storybook/core-server/node_modules/@storybook/core-client/dist/esm/globals/polyfills.js ./node_modules/@storybook/core-server/node_modules/@storybook/core-client/dist/esm/globals/globals.js ./node_modules/webpack-hot-middleware/client.js?reload=true&quiet=false&noInfo=undefined ./node_modules/@pmmmwh/react-refresh-webpack-plugin/client/ErrorOverlayEntry.js ./storybook-init-framework-entry.js ./node_modules/@storybook/addon-docs/dist/esm/frameworks/common/config.js-generated-config-entry.js ./node_modules/@storybook/addon-docs/dist/esm/frameworks/react/config.js-generated-config-entry.js ./node_modules/@storybook/react/dist/esm/client/preview/config-generated-config-entry.js ./node_modules/@storybook/addon-links/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-actions/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-actions/dist/esm/preset/addArgs.js-generated-config-entry.js ./node_modules/@storybook/addon-backgrounds/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-backgrounds/dist/esm/preset/addParameter.js-generated-config-entry.js ./node_modules/@storybook/addon-measure/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-outline/dist/esm/preset/addDecorator.js-generated-config-entry.js ./.storybook/preview.js-generated-config-entry.js ./generated-stories-entry.js

ERROR in ./node_modules/usehooks-ts/dist/esm/useIntersectionObserver/useIntersectionObserver.js 4:25
Module parse failed: Unexpected token (4:25)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| function useIntersectionObserver(elementRef, { threshold = 0, root = null, rootMargin = '0%', freezeOnceVisible = false, }) {
|     const [entry, setEntry] = useState();
>     const frozen = entry?.isIntersecting && freezeOnceVisible;
|     const updateEntry = ([entry]) => {
|         setEntry(entry);
 @ ./node_modules/usehooks-ts/dist/esm/useIntersectionObserver/index.js 1:0-79 1:0-79 2:0-42 2:0-42
 @ ./node_modules/usehooks-ts/dist/esm/index.js
 @ ./src/layouts/notes/notes.tsx
 @ ./src/layouts/notes/notes.stories.js
 @ ./src sync ^\.(?:(?:^|\/|(?:(?:(?!(?:^|\/)\.).)*?)\/)(?!\.)(?=.)[^/]*?\.stories\.(js|jsx|ts|tsx))$
 @ ./generated-stories-entry.js
 @ multi ./node_modules/@pmmmwh/react-refresh-webpack-plugin/client/ReactRefreshEntry.js ./node_modules/@storybook/core-server/node_modules/@storybook/core-client/dist/esm/globals/polyfills.js ./node_modules/@storybook/core-server/node_modules/@storybook/core-client/dist/esm/globals/globals.js ./node_modules/webpack-hot-middleware/client.js?reload=true&quiet=false&noInfo=undefined ./node_modules/@pmmmwh/react-refresh-webpack-plugin/client/ErrorOverlayEntry.js ./storybook-init-framework-entry.js ./node_modules/@storybook/addon-docs/dist/esm/frameworks/common/config.js-generated-config-entry.js ./node_modules/@storybook/addon-docs/dist/esm/frameworks/react/config.js-generated-config-entry.js ./node_modules/@storybook/react/dist/esm/client/preview/config-generated-config-entry.js ./node_modules/@storybook/addon-links/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-actions/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-actions/dist/esm/preset/addArgs.js-generated-config-entry.js ./node_modules/@storybook/addon-backgrounds/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-backgrounds/dist/esm/preset/addParameter.js-generated-config-entry.js ./node_modules/@storybook/addon-measure/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-outline/dist/esm/preset/addDecorator.js-generated-config-entry.js ./.storybook/preview.js-generated-config-entry.js ./generated-stories-entry.js

ERROR in ./node_modules/usehooks-ts/dist/esm/useCopyToClipboard/useCopyToClipboard.js 5:23
Module parse failed: Unexpected token (5:23)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|     const [copiedText, setCopiedText] = useState(null);
|     const copy = async (text) => {
>         if (!navigator?.clipboard) {
|             console.warn('Clipboard not supported');
|             return false;
 @ ./node_modules/usehooks-ts/dist/esm/useCopyToClipboard/index.js 1:0-69 1:0-69 2:0-37 2:0-37
 @ ./node_modules/usehooks-ts/dist/esm/index.js
 @ ./src/layouts/notes/notes.tsx
 @ ./src/layouts/notes/notes.stories.js
 @ ./src sync ^\.(?:(?:^|\/|(?:(?:(?!(?:^|\/)\.).)*?)\/)(?!\.)(?=.)[^/]*?\.stories\.(js|jsx|ts|tsx))$
 @ ./generated-stories-entry.js
 @ multi ./node_modules/@pmmmwh/react-refresh-webpack-plugin/client/ReactRefreshEntry.js ./node_modules/@storybook/core-server/node_modules/@storybook/core-client/dist/esm/globals/polyfills.js ./node_modules/@storybook/core-server/node_modules/@storybook/core-client/dist/esm/globals/globals.js ./node_modules/webpack-hot-middleware/client.js?reload=true&quiet=false&noInfo=undefined ./node_modules/@pmmmwh/react-refresh-webpack-plugin/client/ErrorOverlayEntry.js ./storybook-init-framework-entry.js ./node_modules/@storybook/addon-docs/dist/esm/frameworks/common/config.js-generated-config-entry.js ./node_modules/@storybook/addon-docs/dist/esm/frameworks/react/config.js-generated-config-entry.js ./node_modules/@storybook/react/dist/esm/client/preview/config-generated-config-entry.js ./node_modules/@storybook/addon-links/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-actions/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-actions/dist/esm/preset/addArgs.js-generated-config-entry.js ./node_modules/@storybook/addon-backgrounds/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-backgrounds/dist/esm/preset/addParameter.js-generated-config-entry.js ./node_modules/@storybook/addon-measure/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-outline/dist/esm/preset/addDecorator.js-generated-config-entry.js ./.storybook/preview.js-generated-config-entry.js ./generated-stories-entry.js

ERROR in ./node_modules/usehooks-ts/dist/esm/useEventListener/useEventListener.js 5:38
Module parse failed: Unexpected token (5:38)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|     const savedHandler = useRef();
|     useEffect(() => {
>         const targetElement = element?.current || window;
|         if (!(targetElement && targetElement.addEventListener)) {
|             return;
 @ ./node_modules/usehooks-ts/dist/esm/useEventListener/index.js 1:0-65 1:0-65 2:0-35 2:0-35
 @ ./node_modules/usehooks-ts/dist/esm/index.js
 @ ./src/layouts/notes/notes.tsx
 @ ./src/layouts/notes/notes.stories.js
 @ ./src sync ^\.(?:(?:^|\/|(?:(?:(?!(?:^|\/)\.).)*?)\/)(?!\.)(?=.)[^/]*?\.stories\.(js|jsx|ts|tsx))$
 @ ./generated-stories-entry.js
 @ multi ./node_modules/@pmmmwh/react-refresh-webpack-plugin/client/ReactRefreshEntry.js ./node_modules/@storybook/core-server/node_modules/@storybook/core-client/dist/esm/globals/polyfills.js ./node_modules/@storybook/core-server/node_modules/@storybook/core-client/dist/esm/globals/globals.js ./node_modules/webpack-hot-middleware/client.js?reload=true&quiet=false&noInfo=undefined ./node_modules/@pmmmwh/react-refresh-webpack-plugin/client/ErrorOverlayEntry.js ./storybook-init-framework-entry.js ./node_modules/@storybook/addon-docs/dist/esm/frameworks/common/config.js-generated-config-entry.js ./node_modules/@storybook/addon-docs/dist/esm/frameworks/react/config.js-generated-config-entry.js ./node_modules/@storybook/react/dist/esm/client/preview/config-generated-config-entry.js ./node_modules/@storybook/addon-links/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-actions/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-actions/dist/esm/preset/addArgs.js-generated-config-entry.js ./node_modules/@storybook/addon-backgrounds/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-backgrounds/dist/esm/preset/addParameter.js-generated-config-entry.js ./node_modules/@storybook/addon-measure/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-outline/dist/esm/preset/addDecorator.js-generated-config-entry.js ./.storybook/preview.js-generated-config-entry.js ./generated-stories-entry.js

ERROR in ./node_modules/usehooks-ts/dist/esm/useDarkMode/useDarkMode.js 7:80
Module parse failed: Unexpected token (7:80)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| function useDarkMode(defaultValue) {
|     const isDarkOS = useMediaQuery(COLOR_SCHEME_QUERY);
>     const [isDarkMode, setDarkMode] = useLocalStorage('darkMode', defaultValue ?? isDarkOS ?? false);
|     useUpdateEffect(() => {
|         setDarkMode(isDarkOS);
 @ ./node_modules/usehooks-ts/dist/esm/useDarkMode/index.js 1:0-55 1:0-55 2:0-30 2:0-30
 @ ./node_modules/usehooks-ts/dist/esm/index.js
 @ ./src/layouts/notes/notes.tsx
 @ ./src/layouts/notes/notes.stories.js
 @ ./src sync ^\.(?:(?:^|\/|(?:(?:(?!(?:^|\/)\.).)*?)\/)(?!\.)(?=.)[^/]*?\.stories\.(js|jsx|ts|tsx))$
 @ ./generated-stories-entry.js
 @ multi ./node_modules/@pmmmwh/react-refresh-webpack-plugin/client/ReactRefreshEntry.js ./node_modules/@storybook/core-server/node_modules/@storybook/core-client/dist/esm/globals/polyfills.js ./node_modules/@storybook/core-server/node_modules/@storybook/core-client/dist/esm/globals/globals.js ./node_modules/webpack-hot-middleware/client.js?reload=true&quiet=false&noInfo=undefined ./node_modules/@pmmmwh/react-refresh-webpack-plugin/client/ErrorOverlayEntry.js ./storybook-init-framework-entry.js ./node_modules/@storybook/addon-docs/dist/esm/frameworks/common/config.js-generated-config-entry.js ./node_modules/@storybook/addon-docs/dist/esm/frameworks/react/config.js-generated-config-entry.js ./node_modules/@storybook/react/dist/esm/client/preview/config-generated-config-entry.js ./node_modules/@storybook/addon-links/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-actions/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-actions/dist/esm/preset/addArgs.js-generated-config-entry.js ./node_modules/@storybook/addon-backgrounds/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-backgrounds/dist/esm/preset/addParameter.js-generated-config-entry.js ./node_modules/@storybook/addon-measure/dist/esm/preset/addDecorator.js-generated-config-entry.js ./node_modules/@storybook/addon-outline/dist/esm/preset/addDecorator.js-generated-config-entry.js ./.storybook/preview.js-generated-config-entry.js ./generated-stories-entry.js

Do you know why? And how I can solve it?

Thanks!

Allow react 16

Hi,

I know this is not really a good practice to allow an old release of a vendor dependency, but as described on the official blog posts, react 17 does not has "real breaking change" as it's a preparation state for react 18.

For now, many libraries and popular react ecosystem tools looks "not ready" to react 17, according to the NPM numerous conflict issues.

Allowing react 16 will allow more integration of your library during this period without the dependencies conflict problematic.
Plus, no code adaption should be required, but I can not be 100% sure at this point.

May you consider this request?

Regards

useEventListener logic is broken

usually in the first cycle the element ref is null and even though a ref element is present it will attach a listener to the window object. If ref is given it should wait until ref.current is available before attaching any events

Publish on npm?

This great repo sounds like a great candidate for publishing on npm for easier updating and security auditing. If someone knows how to set it up, it could also support tree shaking, since each of the hooks is in its own file.

What do you think?

[useFetch] Fetch State is not exported

I want to wrap useFetch to do lazy loading fetch.

import { State, useBoolean } from "usehooks-ts";
import React from "react";

const setFetch: React.useState<State | undefined>(undefined);
const isClicked = useBoolean();

React.useEffect(
    function () {
      if(isClicked.value) {
        setFetch(useFetch<whatever>(url)
      }
    }
    [isClicked, setFetch],
);

useDarkMode Next.js issue

When using the hook useDarkMode and I presume it could be the same issue for other hooks with Next.js framework and Material-UI, I get the error message: Prop className did not match.

In the console log, the error refer to the documentation: https://nextjs.org/docs/messages/react-hydration-error

Here is my current code generating this error:

const { isDarkMode } = useDarkMode()

const theme = useMemo(
    () =>
      createTheme(themeOptions(isDarkMode ? 'dark' : 'light')),
    [isDarkMode]
  )

The way I was able to fix this error to happen was changing my code to:

  const [dark, setDark] = useState(false)
  const { isDarkMode } = useDarkMode()

  useEffect(() => {
    setDark(isDarkMode)
  }, [isDarkMode])

  const theme = useMemo(
    () =>
      createTheme(themeOptions(dark ? 'dark' : 'light')),
    [dark]
  )

I do not know if this error is actually related to the hooks or maybe with the useMemo hook instead!

`setValue` should be referentially stable

The setValue for useLocalStorage should be stored in a ref and a callback should be returned that invokes that ref i.e.

const setValueRef = useRef();

setValueRef.current = (value) => { ... } // existing logic goes here

const setValue = useCallback((value) => setValueRef.current?.(value), []);

This allows that setValue (like setValue returned from useState is referentially stable and does not need to be included as a dep in functions wrapped in useCallback that use this method.

Production build can no longer be successfully completed after 2.2.2 upgrade

Hello there!

There is an error I can see after the recent changes made to the ESM/CJS build setup.
It takes place when I try to execute npm run build with NODE_ENV=production. Here is the output:

#29 2.550 Creating an optimized production build...
#29 40.40 Failed to compile.
#29 40.40 
#29 40.40 ./node_modules/usehooks-ts/dist/esm/useLocalStorage/useLocalStorage.js 53:65
#29 40.40 Module parse failed: Unexpected token (53:65)
#29 40.40 File was processed with these loaders:
#29 40.40  * ./node_modules/react-scripts/node_modules/babel-loader/lib/index.js
#29 40.40 You may need an additional loader to handle the result of these loaders.
#29 40.40 | function parseJSON(value) {
#29 40.40 |   try {
#29 40.40 >     return value === 'undefined' ? undefined : JSON.parse(value ?? '');
#29 40.40 |   } catch (error) {
#29 40.40 |     console.log('parsing error on', {
#29 40.40 
#29 40.40 

I went down to the node_modules/usehooks-ts/dist/ folder and checked if there is any difference between the latest and the workable versions. There was a difference indeed:

In the latest 2.3.0, it was exactly as it is shown above:

try {
  return value === 'undefined' ? undefined : JSON.parse(value ?? '');
}

However in the last working 2.2.1, it was precompiled:

try {
  return value === 'undefined' ? undefined : JSON.parse(value !== null && value !== void 0 ? value : '');
}

I guess I could include the package in my local babel pipeline to mitigate the issue.
However, I'm not an expert in modern js build things and I'm not sure whether this issue should be solved on my side or yours.

`useLocalStorage` creates warning in Next.JS

Next JS prebuilds pages, so when using the useLocalStorage hook it creates a warning link

Warning: Text content did not match. Server: "Initial Value" Client: "Stored Value"

[useLocalStorage] does not accept undefined in setter

When a state can be undefined, this hook does not support setting an undefined value.

In this example, you can set state to a string, but if you set it to undefined it will just return the initial value

import useLocalStorage from "app/hooks/useLocalStorage"

export default function Test() {
  const [state, setState] = useLocalStorage<string | undefined>("someKey", "initial")

  return (
    <div>
      <button onClick={() => setState("new value")}>String</button>
      <button onClick={() => setState(undefined)}>undefined</button>
      {state}
    </div>
  )
}

This is because of this line in the code where if item does not exist we do not parse it.

return item ? (JSON.parse(item) as T) : initialValue

funnily enough undefined cannot be stored in localstorage, so it gets set as "undefined" and then causes a JSON.parse error that means we return the initial value anyway.

Question: How to test `useLocalStorage`

Actually I am using useLocalStorage and writing unit tests around it and I am getting below error. I am using Jest & react-testing-library.

/node_modules/react-dom/cjs/react-dom.development.js:3905
      var evt = document.createEvent('Event');
                         ^

TypeError: Cannot read property 'createEvent' of null

Add `useSessionStorage` hook to complement `useLocalStorage`

Hi there! Really impressed by this collection of hooks, nice work, and thanks for sharing!

I'd love to see a useSessionStorage hook alongside useLocalStorage and wanted to add a note here to add one. If I get time I may PR one, but no promises :)

I couldn't find any well-supported hooks that support local and session storage both, but your useLocalStorage hook seems like one of the more solid ones.

Thank you πŸŽ‰

can/t deploy on cloudflare build error - useEventListener()

17:37:06.484 Initializing build environment. This may take up to a few minutes to complete
17:39:30.143 Success: Finished initializing build environment
17:39:30.143 Cloning repository...
17:39:34.249 Success: Finished cloning repository files
17:39:35.123 Installing dependencies
17:39:35.126 Python version set to 2.7
17:39:36.152 Downloading and installing node v12.22.0...
17:39:36.313 Downloading https://nodejs.org/dist/v12.22.0/node-v12.22.0-linux-x64.tar.xz...
17:39:36.528 Computing checksum with sha256sum
17:39:36.634 Checksums matched!
17:39:38.947 Now using node v12.22.0 (npm v6.14.11)
17:39:39.041 Started restoring cached build plugins
17:39:39.044 Finished restoring cached build plugins
17:39:39.196 Attempting ruby version 2.7.1, read from environment
17:39:40.388 Using ruby version 2.7.1
17:39:40.706 Using PHP version 5.6
17:39:40.744 5.2 is already installed.
17:39:40.751 Using Swift version 5.2
17:39:40.752 Started restoring cached node modules
17:39:40.755 Finished restoring cached node modules
17:39:40.973 Installing NPM modules using NPM version 6.14.11
17:39:42.801 npm WARN deprecated @material-ui/[email protected]: You can now upgrade to @mui/material. See the guide: https://mui.com/guides/migration-v4/
17:39:42.818 npm WARN deprecated @material-ui/[email protected]: You can now upgrade to @mui/icons. See the guide: https://mui.com/guides/migration-v4/
17:39:43.508 npm WARN deprecated @material-ui/[email protected]: You can now upgrade to @mui/system. See the guide: https://mui.com/guides/migration-v4/
17:39:44.436 npm WARN deprecated @material-ui/[email protected]: You can now upgrade to @mui/styles. See the guide: https://mui.com/guides/migration-v4/
17:40:07.346
17:40:07.346 > @fortawesome/[email protected] postinstall /opt/buildhome/repo/node_modules/@fortawesome/fontawesome-common-types
17:40:07.346 > node attribution.js
17:40:07.346
17:40:07.401 Font Awesome Free 0.3.0 by @FontAwesome - https://fontawesome.com
17:40:07.401 License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
17:40:07.401 Copyright {{currentYear}} Fonticons, Inc.
17:40:07.401
17:40:07.414
17:40:07.414 > @fortawesome/[email protected] postinstall /opt/buildhome/repo/node_modules/@fortawesome/free-brands-svg-icons/node_modules/@fortawesome/fontawesome-common-types
17:40:07.414 > node attribution.js
17:40:07.414
17:40:07.472 Font Awesome Free 0.2.36 by @FontAwesome - https://fontawesome.com
17:40:07.472 License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
17:40:07.472
17:40:07.479
17:40:07.479 > @fortawesome/[email protected] postinstall /opt/buildhome/repo/node_modules/@fortawesome/free-solid-svg-icons/node_modules/@fortawesome/fontawesome-common-types
17:40:07.479 > node attribution.js
17:40:07.479
17:40:07.547 Font Awesome Free 0.2.36 by @FontAwesome - https://fontawesome.com
17:40:07.548 License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
17:40:07.548
17:40:07.560
17:40:07.560 > @fortawesome/[email protected] postinstall /opt/buildhome/repo/node_modules/font-awesome-5-pro-regular/node_modules/@fortawesome/fontawesome-common-types
17:40:07.560 > node attribution.js
17:40:07.560
17:40:07.617 Font Awesome Free 0.2.36 by @FontAwesome - https://fontawesome.com
17:40:07.617 License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
17:40:07.617
17:40:07.638
17:40:07.638 > @fortawesome/[email protected] postinstall /opt/buildhome/repo/node_modules/@fortawesome/fontawesome-svg-core
17:40:07.638 > node attribution.js
17:40:07.638
17:40:07.696 Font Awesome Free 1.3.0 by @FontAwesome - https://fontawesome.com
17:40:07.696 License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
17:40:07.696 Copyright {{currentYear}} Fonticons, Inc.
17:40:07.696
17:40:07.704
17:40:07.704 > @fortawesome/[email protected] postinstall /opt/buildhome/repo/node_modules/@fortawesome/free-brands-svg-icons
17:40:07.704 > node attribution.js
17:40:07.704
17:40:07.761 Font Awesome Free 5.15.4 by @FontAwesome - https://fontawesome.com
17:40:07.761 License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
17:40:07.761
17:40:07.772
17:40:07.772 > @fortawesome/[email protected] postinstall /opt/buildhome/repo/node_modules/@fortawesome/free-solid-svg-icons
17:40:07.772 > node attribution.js
17:40:07.772
17:40:07.826 Font Awesome Free 5.15.4 by @FontAwesome - https://fontawesome.com
17:40:07.826 License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
17:40:07.826
17:40:07.834
17:40:07.834 > [email protected] postinstall /opt/buildhome/repo/node_modules/font-awesome-5-pro-regular
17:40:07.834 > node attribution.js
17:40:07.834
17:40:07.893 Font Awesome Pro 5.15.2 by @FontAwesome - https://fontawesome.com
17:40:07.893 License - https://fontawesome.com/license (Commercial License)
17:40:07.893
17:40:08.055 npm notice created a lockfile as package-lock.json. You should commit this file.
17:40:08.062 npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @next/[email protected] (node_modules/next/node_modules/@next/swc-android-arm64):
17:40:08.062 npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for @next/[email protected]: wanted {"os":"android","arch":"arm64"} (current: {"os":"linux","arch":"x64"})
17:40:08.068 npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @next/[email protected] (node_modules/next/node_modules/@next/swc-darwin-arm64):
17:40:08.068 npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for @next/[email protected]: wanted {"os":"darwin","arch":"arm64"} (current: {"os":"linux","arch":"x64"})
17:40:08.074 npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @next/[email protected] (node_modules/next/node_modules/@next/swc-darwin-x64):
17:40:08.074 npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for @next/[email protected]: wanted {"os":"darwin","arch":"x64"} (current: {"os":"linux","arch":"x64"})
17:40:08.080 npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @next/[email protected] (node_modules/next/node_modules/@next/swc-linux-arm-gnueabihf):
17:40:08.080 npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for @next/[email protected]: wanted {"os":"linux","arch":"arm"} (current: {"os":"linux","arch":"x64"})
17:40:08.085 npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @next/[email protected] (node_modules/next/node_modules/@next/swc-linux-arm64-gnu):
17:40:08.085 npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for @next/[email protected]: wanted {"os":"linux","arch":"arm64"} (current: {"os":"linux","arch":"x64"})
17:40:08.091 npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @next/[email protected] (node_modules/next/node_modules/@next/swc-linux-arm64-musl):
17:40:08.091 npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for @next/[email protected]: wanted {"os":"linux","arch":"arm64"} (current: {"os":"linux","arch":"x64"})
17:40:08.096 npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @next/[email protected] (node_modules/next/node_modules/@next/swc-win32-arm64-msvc):
17:40:08.096 npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for @next/[email protected]: wanted {"os":"win32","arch":"arm64"} (current: {"os":"linux","arch":"x64"})
17:40:08.102 npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @next/[email protected] (node_modules/next/node_modules/@next/swc-win32-ia32-msvc):
17:40:08.102 npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for @next/[email protected]: wanted {"os":"win32","arch":"ia32"} (current: {"os":"linux","arch":"x64"})
17:40:08.109 npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @next/[email protected] (node_modules/next/node_modules/@next/swc-win32-x64-msvc):
17:40:08.109 npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for @next/[email protected]: wanted {"os":"win32","arch":"x64"} (current: {"os":"linux","arch":"x64"})
17:40:08.120 npm WARN [email protected] requires a peer of react@^0.14 || ^15.0.0-rc || ^15.0 || ^16.0.0 || ^16.0 but none is installed. You must install peer dependencies yourself.
17:40:08.129 npm WARN [email protected] requires a peer of react-dom@^0.14 || ^15.0.0-rc || ^15.0 || ^16.0.0 || ^16.0 but none is installed. You must install peer dependencies yourself.
17:40:08.139 npm WARN [email protected] requires a peer of webpack@^4.0.0 || ^5.0.0 but none is installed. You must install peer dependencies yourself.
17:40:08.140
17:40:08.142 added 170 packages from 198 contributors and audited 180 packages in 26.371s
17:40:08.245
17:40:08.245 19 packages are looking for funding
17:40:08.245 run npm fund for details
17:40:08.245
17:40:08.245 found 0 vulnerabilities
17:40:08.246
17:40:08.278 NPM modules installed
17:40:08.555 Installing Hugo 0.54.0
17:40:09.237 Hugo Static Site Generator v0.54.0-B1A82C61A/extended linux/amd64 BuildDate: 2019-02-01T10:04:38Z
17:40:09.238 Started restoring cached go cache
17:40:09.242 Finished restoring cached go cache
17:40:09.274 go version go1.14.4 linux/amd64
17:40:09.280 go version go1.14.4 linux/amd64
17:40:09.282 Installing missing commands
17:40:09.282 Verify run directory
17:40:09.282 Executing user command: next build && next export
17:40:10.068 warn - SWC minify release candidate enabled. https://nextjs.org/docs/messages/swc-minify-enabled
17:40:10.072 warn - No build cache found. Please configure build caching for faster rebuilds. Read more: https://nextjs.org/docs/messages/no-cache
17:40:10.093 Attention: Next.js now collects completely anonymous telemetry regarding usage.
17:40:10.093 This information is used to shape Next.js' roadmap and prioritize features.
17:40:10.093 You can learn more, including how to opt-out if you'd not like to participate in this anonymous program, by visiting the following URL:
17:40:10.093 https://nextjs.org/telemetry
17:40:10.093
17:40:10.147 info - Checking validity of types...
17:40:10.275 warn - No ESLint configuration detected. Run next lint to begin setup
17:40:10.281 info - Creating an optimized production build...
17:40:31.923 info - Compiled successfully
17:40:31.924 info - Collecting page data...
17:40:33.958
17:40:33.958 > Build error occurred
17:40:33.962 /opt/buildhome/repo/node_modules/usehooks-ts/dist/cjs/useEventListener/useEventListener.js:7
17:40:33.962 const targetElement = element?.current || window;
17:40:33.962 ^
17:40:33.962
17:40:33.962 SyntaxError: Unexpected token '.'
17:40:33.962 at wrapSafe (internal/modules/cjs/loader.js:915:16)
17:40:33.962 at Module._compile (internal/modules/cjs/loader.js:963:27)
17:40:33.962 at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
17:40:33.962 at Module.load (internal/modules/cjs/loader.js:863:32)
17:40:33.962 at Function.Module._load (internal/modules/cjs/loader.js:708:14)
17:40:33.962 at Module.require (internal/modules/cjs/loader.js:887:19)
17:40:33.962 at require (internal/modules/cjs/helpers.js:74:18)
17:40:33.962 at Object. (/opt/buildhome/repo/node_modules/usehooks-ts/dist/cjs/useEventListener/index.js:17:26)
17:40:33.962 at Module._compile (internal/modules/cjs/loader.js:999:30)
17:40:33.962 at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10) {
17:40:33.962 type: 'SyntaxError'
17:40:33.962 }
17:40:34.007 Failed: build command exited with code: 1

Event bubbling

Hi :)

What if i need an event bubbling ?

targetElement.addEventListener(eventName, eventListener, bubbling || false) return () => { targetElement.removeEventListener(eventName, eventListener, bubbling || false) } }, [eventName, element])

React dependency uses incorrect notation to allow React 17

I see in v1.0.8 that the react dependency was changed to ^16.8.0 but I believe this was done in error since the package does not support projects that use v17+. I believe this can be fixed with an easy change:

"dependencies": {
  "react": ">=16.8.0",
},
"peerDependencies": {
  "react": ">=16.8.0",
}

Let me know if you'd like me to submit a PR for this

setValue of useLocalStorage should not change at each rerender

The setValue setter function returned by useLocalStorage is re-evaluated every time,
resulting in a lot of re-writes when it is specified as a dependency of an effect or callback (while skipping including it as dependency sometimes results in missing storage write).

I suspect it should be wrapped in something like useCallback(..., [setStoredValue]) to return a more "stable" object avoiding that issue.

threshold as array

About useIntersectionObserver

passing threshold as an array of positions to observe will result in endless state changes, as every entry differs and the whole entry is set to the state:

const entry = useIntersectionObserver(ref, { threshold: [0.2, 0.4, 0.6] })

There should be a condition to set a new state only if relevant changes have happened...

The example in useDarkMode() doesn't work

In the example of useDarkMode() hook, when I click the button, the text color and the background color doesn't change. Please fix it, preferably using tailwind classes

useLocalStorage: Unsafe return of an any typed value @typescript-eslint/no-unsafe-return

My linter is kicking up a fuss on the useLocalStorage hook:

Line 17:7:  Unsafe return of an any typed value  @typescript-eslint/no-unsafe-return

My .eslintrc.js:

module.exports = {
  parser: '@typescript-eslint/parser',
  parserOptions: {
    project: 'tsconfig.json',
    sourceType: 'module',
  },
  plugins: ['@typescript-eslint/eslint-plugin'],
  extends: [
    'react-app',
    'react-app/jest',
    'plugin:@typescript-eslint/recommended',
    "plugin:@typescript-eslint/recommended-requiring-type-checking",
    'plugin:prettier/recommended',
  ],
  root: true,
  env: {
    node: true,
    jest: true,
  },
  ignorePatterns: ['.eslintrc.js'],
  rules: {
    '@typescript-eslint/no-empty-interface': 'off',
    '@typescript-eslint/explicit-function-return-type': 'off',
    '@typescript-eslint/explicit-module-boundary-types': 'off',
  },
}

And .tsconfig.json:

{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx"
  },
  "include": ["src"]
}

Is there any way to get the hook to work under these conditions?

does useIsMounted need to have its returned function wrapped in useCallback?

In useIsMounted, the function returns () => isMounted.current. Then in the usage example, when this function is invoked in a useEffect, the eslint disable flag // eslint-disable-next-line react-hooks/exhaustive-deps is used as it would otherwise warn that isMounted should be included (which would cause a loop as it changes on every render).

Instead, should the useIsMounted hook not wrap the return function in a useCallback? i.e. return useCallback(() => mounted.current, []); ?

This seems to work well on my project.

useEffectOnce never calls the cleanup function

With this change: #143 The useEffectOnce hook now no longer calls the cleanup function:

import { useState, useEffect } from "react";
import { useEffectOnce } from "usehooks-ts";

function SubComponent() {
  // This useEffect code works as expected, but in strict mode gets run twice
  // useEffect(() => {
  //   console.log("useEffect Mounted");
  //   return () => {
  //     console.log("useEffect Unmounted");
  //   };
  // });
  
  useEffectOnce(() => {
    console.log("useEffectOnce Mounted");
    return () => {
      // This never gets called
      console.log("useEffectOnce Unmounted");
    };
  });
  
  return <div>Hello</div>;
}

function App() {
  const [mounted, setMounted] = useState(true);
  return (
    <div>
      <button onClick={() => setMounted(false)}>Unmount</button>
      {mounted && <SubComponent />}
    </div>
  );
}

You can try this out live here:

https://codesandbox.io/s/angry-diffie-fj3ek6?file=/src/App.js

This fix comes from a blog post on AG-Grid that I think is also in error. That code assumes that the custom hook gets called to set renderAfterCalled to true, probably on the assumption that putting a console.log at that point will show it getting called twice, but it really doesn't get called twice, that second log is just react-devtools.

I actually have no idea about how to fix this the right way. There doesn't seem to be a way to detect strict mode, safely, externally to React.

Suggestion: Use mouseenter and mouseleave in the useHover hook

I used the useHover code in a project--thank you!--and noticed one downside. Because mouseover and mouseout are used for the event listeners, there is a lot of fluttering back-and-forth between true and false because these events trigger not just when entering and leaving the element in question but also when entering and leaving any child of that element.

In my case, I had the useHover hook on an icon button, and the hover value would flip back and forth when the cursor was already inside the button but moving back and forth over the icon! Needless to say, this behavior was unexpected to me, but easily resolved by moving from over to enter and out to leave.

Something to consider!

Thank you for your hard work on this project. :)

Dark mode: weird behaviour on site

Description

A few times I've already discovered that when I'm going to the side and I'm switching between dark mode and light mode it has some issues. Sometimes when I click the button on the navigation it's only changing a particular part of the site or not even doing anything.

Checked

I've already checked if it's happening on localhost, but there I didn't face this problem. It's quite weird for me that it's only happening in production. Maybe someone else could also take a look at what've I found.

Details

When I found this bug I was using Google Chrome, but I also noticed it on phone. I made a short video to illustrate it.

Screen.Recording.2021-11-25.at.18.34.09.mov

useElementSize doesn't update size when elementRef.current changes

Summary

If elementRef.current within useElementSize starts out as null on initial render (typically because the target element does not render), useElementSize will not update and return the correct element size once elementRef.current changes to a non-null value.

Simplified code example

const FullScreenDialog = ({ open, title, msg }: { open: boolean; title: string; msg: string }) => {
    const hdrRef = useRef(null);
    const { height: winHeight } = useWindowSize();
    const { height: hdrHeight } = useElementSize(hdrRef);

    if (!open) return null;
    return (
        <div>
            <div ref={hdrRef}>{title}</div>
            <div style={{ height: winHeight - hdrHeight, marginTop: hdrHeight }}>{msg}</div>
        </div>
    );
};

Details

I'm using useElementSize in a full screen dialog component similar to the simplified one above. The dialog component starts out as not open (open=false), so on first render, it returns null. This means that the dialog header element I want the size of doesn't render at all on initial render and therefore, elementRef.current is null. The useLayoutEffect within useElementSize runs and calls handleSize, but because elementRef.current is null, setSize does not get called and so useElementSize returns { width: 0, height: 0 }. This is all working as expected so far.

Then, the user clicks a button to open the dialog. So my dialog component re-renders, but now with open=true so it renders to the actual elements of the dialog component. Now elementRef.current becomes an actual node. However, there is nothing that causes handleSize to get called again, so useElementSize will always return { width: 0, height: 0 }. (Note: resizing the window does cause handleSize to get called and then useElementSize returns the correct element size.)

Suggested fix

I believe the fix is simple: add elementRef?.current to the item list in the call to useLayoutEffect. Then, on a subsequent re-render of useElementSize, when elementRef?.current changes from null to non-null, handleSize will get called and the size will be updated.

Other info

This could possibly be related to #32.

Mistake in Documentation Page

I found a mistake in Documentation in https://usehooks-ts.com/react-hook/use-fetch.

Where I found a a tag with wrong href attribute.
Line 4 in useLocalStorage() link is https://usehooks-ts.com/react-hook/use-fetch instead of
https://usehooks-ts.com/react-hooks/use-fetch. Change /react-hook/ as /react-hooks/.

SSR issue using `useLayoutEffect()` with Nextjs

I use useHover in my next app and have this error message:

Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server 
renderer's output format. This will lead to a mismatch between the initial, non-hydrated UI and the intended 
UI. To avoid this, useLayoutEffect should only be used in components that render exclusively on the client. 
See https://reactjs.org/link/uselayouteffect-ssr for common fixes.

Solution:

Something like:

import { useEffect, useLayoutEffect } from 'react';

const useIsomorphicLayoutEffect =
  typeof window !== 'undefined' ? useLayoutEffect : useEffect;

export default useIsomorphicLayoutEffect;

useIntersectionObserver unexpected token

I'm running 2.0.2 just fine and when I upgrad eto 2.2.2:

./node_modules/usehooks-ts/dist/esm/useIntersectionObserver/useIntersectionObserver.js 11:23
Module parse failed: Unexpected token (11:23)
File was processed with these loaders:
 * ./node_modules/react-scripts/node_modules/babel-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.
|   } = _ref;
|   const [entry, setEntry] = useState();
>   const frozen = entry?.isIntersecting && freezeOnceVisible;
| 
|   const updateEntry = _ref2 => {

useElementSize() returns 0 width/height if initially rendered to the DOM within a parent with display: none

When the element to be sized is within another element that's conditionally hidden/shown via display none/block, the hook can't determine its size once the parent is visible. If you resize the browser, then the size will be correct at the time of resize. However, if you hide the parent, the element will still report its size as being present.

For my use case, having a non-zero size reported once the parent is hidden isn't a problem, though reporting a size of 0x0 (until browser resize) is a problem. I've forked your hook demo so that it reproduces the issue.

https://codesandbox.io/s/usehooks-ts-react-component-template-forked-tzw9yv?file=/src/App.tsx
Possibly related to #32

Ask: Do we have anyway limit key that calls from useLocalStorage?

Do we have anyway limit key that calls from useLocalStorage? My app has a lot of things that I want to save in local storage.
But I want to use something to limit keys for read-write for example I don't know how to use an enum with useLocalStorage.
I am new to Typescript.

Close: I think I need to learn basic Typescript first.

CRA5 source map warning

Hi team.
I'm getting this error with create-react-app 5.0 for all hooks.

WARNING in ./node_modules/usehooks-ts/esm/useWindowSize/useWindowSize.js
Module Warning (from ./node_modules/source-map-loader/dist/cjs.js):
Failed to parse source map from '$REPO_ROOT/node_modules/usehooks-ts/src/useWindowSize/useWindowSize.ts' file: Error: ENOENT: no such file or directory, open '$REPO_ROOT/node_modules/usehooks-ts/src/useWindowSize/useWindowSize.ts'

And it has been complained a lot here:
facebook/create-react-app#11767

Should we add some source map support?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.