Code Monkey home page Code Monkey logo

react-hook's Introduction

↩ react-hook

Strongly typed React hooks for function components



Hook Description
useAsync() A React hook for gracefully resolving, cancelling, and handling errors for async functions and promises.
useCache() A React hook for accessing an asynchronous key/value cache that persists data between renders and components. This allows you to do neat stuff like preload data before your next page or component has even started mounting.
useChange() A React hook that invokes a callback anytime a value changes
useClick() A React hook for conditionally firing a function when an element is clicked - for instance if you only want a click even to fire on double-clicks.
useCopy() A React hook for copying text to the clipboard
useCounter() A React hook counter with min/max/step/cast options
useDebounce() A React hook for debouncing setState and other callbacks
useEvent() A React hook for adding events to HTML elements. This hook cleans up your listeners automatically when it unmounts. You won't have to worry about wrapping your listener in a useCallback() because this hook makes sure your most recent callback is always invoked.
useGoogleOptimize() A React hook for adding Google Optimize variants to components.
useHotkey() A React hook for invoking a callback when hotkeys are pressed. This hook also provides interop between event.key and event.which - you provide a string, and the library turns it into an event.which key code if it has to.
useHover() A React hook for tracking the hover state of DOM elements in browsers where hovering is possible. If the browser does not support hover states (e.g. a phone) the isHovering value will always be false.
useIntersectionObserver() A React hook for the IntersectionObserver API that uses a polyfill when the native API is not available.
useLatest() A React hook that updates useRef().current with the most recent value each invocation
useMediaQuery() React hooks that update when media queries change between matched and unmatched states.
useMergedRef() A React hook for merging multiple refs into one ref.
useMousePosition() A React hook for tracking the position, hover, and "down" state of the mouse as it interacts with an element. This hook provides interoperability between touch and desktop devices and will treat ontouch events the same as onmouse ones. Additionally, this hook is throttled to 30fps by default using a useThrottle() hook, though the precise frame rate is configurable.
usePassiveLayoutEffect() A React hook that uses useEffect() on the server and useLayoutEffect() in the browser
usePrevious() A React hook that stores a value from the previous render
useResizeObserver() A React hook that fires a callback whenever ResizeObserver detects a change to its size.
useServerPromises() A React hook for continuously rendering a React tree until no promises are pushed to server-promises's context in a given render
useSize() A React hook for measuring the size of HTML elements including when they change
useSwitch() A React hook for controlling a boolean value with toggle, on, and off callbacks.
useThrottle() A React hook for throttling setState and other callbacks.
useToggle() A React hook for toggling between two values with a callback.
useWindowScroll() A React hook for updating components when the scroll position of the window on the y-axis changes.
useWindowSize() React hooks for updating components when the size of the window changes.

Note on IE11

If you need support for legacy browsers you will have to do what you should be doing already anyway and compile your dependencies to your desired target. This library does not ship transformations for browsers the maintainer doesn't care about performing maintenance for.

Contributing

👋 Click here to see how to contribute

LICENSE

MIT

react-hook's People

Contributors

albertpurnama avatar bluenote10 avatar cascornelissen avatar coopermaruyama avatar dafrok avatar daphnesmit avatar eaglus avatar fishmandev avatar flekschas-ozette avatar genk1 avatar hipstersmoothie avatar jantimon avatar jaredlunde avatar melanieseltzer avatar psd-coder avatar romms avatar skoob13 avatar szogun1987 avatar tony avatar weotch avatar xananax avatar yomed 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

react-hook's Issues

[Mouse Position] `isDown` is never true on mobile

on Mobile, isDown is never true. Pressing triggers isOver only.

To Reproduce
Steps to reproduce the behavior:

  1. Open https://r0xlt.csb.app/ on your mobile (or open devTools and toggle the mobile emulator)
  2. Tap and drag
  3. Notice that isOver is true, but isDown is not true

The code is available here on CodeSandbox (a small change from the README example). Relevant part reproduced here for convenience:

const App = () => {
  const [mousePosition, ref] = useMousePosition()
  return <div ref={ref}>
      isOver: {mousePosition.isOver ? 'true' : 'false'}<br/>
      isDown: {mousePositition.isDown ? 'true' : 'false'}<br/>
    </div>
}

Expected behavior
"hover" state can't be detected on mobile, obviously, but isDown should be true if the user has tapped. Without it, it's impossible to detect a drag or long press.

useLatest() creates reference to a value from the previous render

Describe the bug
When I call useLatest, I expect to receive a ref object containing the value I pass to it. The current implementation updates the value with a useEffect callback. This will eventually update the ref, but by then, the code that actually needs the new value to render the component has already run.

To Reproduce

function ComponentWithLatestRef() {
  const value = compute();
  const valueRef = useLatest(value);
  console.log(value === valueRef.current); // `false` when value differs from the last render
  useHook(opts, valueRef); // receives an old value
  
  return <div>...</div>
}

Expected behavior
The ref should be updated inline while the component renders. The existing behavior would be more accurately described by usePreviousAndUpdate(value).

Additional context
This is present in @react-hook/latest 1.0.3

[debounce] Possibility to set state immediately

First of all, awesome library!

Is your feature request related to a problem? Please describe.

A frequent use case of mine is that I want to set a certain state both

  • debounced, when the input comes from the user, i.e., setState is called in an event handler, and
  • immediately, when a state change is not triggered by raw user input, for instance, calling setState to reset a search term value.

Describe the solution you'd like

On first glance, it would be pretty straightforward to include this functionality in useDebounce:

const [value, setValueDebounced, setValueImmediate] = useDebounce(...)

An event handler could now use setValueDebounced while other code may want to use setValueImmediate.

Basically this line would have to return state[1] as third value. For standard usage this should be a non-breaking change, because the array just gets an additional value.

I could prepare a PR if you can fancy the feature.

Describe alternatives you've considered

An alternative design would be to pass the debounce value into each set state call, i.e. setValue("foo", 1000) for debounced, and setValue("foo", 0) for immediate.

However this would be a bigger change, and would probably require to introduce a new hook useVariableDebounce.

usePassiveLayoutEffect webpack error in production build

Describe the bug
Getting a super weird error when building with webpack in production mode.

passive_layout_effect_dist_module is not a function.

Have you guys already experienced something like that? Could someone point me in the right direction maybe?

Possible Bug based On Code Comments

Describe the bug
This isn't necessarily a bug, however I thought I would point it out in case it is unintentional.

The useTimeoutCallback function here, only has 2 parameters (callback and ms) however the code comment here references an additional dependencies parameter.

Not sure if this is a code comment that is stale or additional code that is missing.

I hope this was helpful, thanks!

@react-hook/window-size: width and height are not synced causing an extra re-render

Hi, thanks for the library. It's super helpful.

I am using

const [width, height] = useWindowSize()

However, as it turns out width and height are not in sync, which means that I get a new width, but still have the old height. As a consequence, when I am changing the screen size, my component re-renders two times instead of one time. It first re-renders for width and then for height. I have come up with the following workaround, but I do not really like it:

import { useState, useEffect } from "react"
import { connect } from "react-redux"
import { useWindowSize } from "@react-hook/window-size"
import { windowSizeUpdate } from "../../redux/actions/settings"

const DeviceSize = ({ dispatch }) => {
  const [width, height] = useWindowSize()
  const [windowSize, setWindowSize] = useState({ width, height })

  useEffect(() => {
    if (width !== windowSize.width) {
      setWindowSize({ width, height })
    } else if (height !== windowSize.height) {
      setWindowSize({ width, height })
    } else if (width !== height && windowSize.width !== windowSize.height) {
      let payload = { windowSize }
      dispatch(windowSizeUpdate(payload))
    }
  }, [dispatch, windowSize, height, width])

  return null
}

export default connect()(DeviceSize)

Is there a fix for this behaviour or a better solution? Thanks a lot.

[useMediaQuery] React hydration doesn't re-evaluate the hook

Describe the bug

Next.JS does SSR and this hook sends a false first and then React doesn't update when it client-side detects a true. I made a work-around that makes it work. I am not sure what what internals make this problem occur.

To Reproduce

const isDesktop = useMediaQuery("(min-width:900px)");

I return different HTML depending on whether isDesktop is true or false and it seems like React assumes that that the HTML it got from the server was with isDesktop = true while it was when isDesktop = false. For things like this I have always made a useEffect to change the value and not useState(theCurrentValue) which would cause a discrepancy between server and browser.

Expected behavior
Correctly rendered HTML.

Here is my work-around that makes this work regardless:

  const isDesktop_ = useMediaQuery("(min-width:900px)");

  const [isDesktop, setIsDesktop] = useState(false);

  // Work-around for server-side render
  useEffect(() => {
    setIsDesktop(isDesktop_);
  }, [isDesktop_]);

React-cache sometimes falls into infinite loop

Describe the bug
An application that uses cache sometimes freezes,

To Reproduce
Steps to reproduce the behavior:

  1. Create a component that uses a cached value with the given key
  2. Create another component that uses a cached value with the same key
  3. Remove the second component from the components tree
  4. Write a new value for the watched key
  5. Application freezes

Expected behavior
The remaining component should be refreshed,

Screenshots
None

Desktop (please complete the following information):

  • OS: found on Windows and Mac
  • Browser: found on Edge, Chrome, Safari and Firefox
  • Version: pretty current

Smartphone (please complete the following information):
Not tested on mobile

Additional context
PR is already prepared

useDebounce() only supports initialValue and not value as input, so it may be unnecessarily verbose, without providing immediate state

Hook useDebounce(initialState, wait?, leading?) uses initial state property as a first param (which lacks description in Readme and can feel ambiguous until tested), unlike some other debounce implementations like:
https://usehooks.com/useDebounce/
https://github.com/xnimorz/use-debounce
which use the input value directly instead. If this decision was made intentionally, I would suggest that the intended use-case could be at least addressed in the documentation, because right now if the user prefers a behavior where they can access both the immediate and debounced inputs (for example to do immediate client-sided validation but also debounced server-sided calls), the least verbose solution (using also a state hook) is probably writing the following block:

const [debouncedInput, setDebouncedInput] = useDebounce(input);
setDebouncedInput(input);

Note that this doesn't really feel optimized due to the fact that you have to call the setter outside a hook, so the user may assume some additional overhead and not feel comfortable about it, as there's nothing similar documented yet. Note that with input as a parameter, there wouldn't be any need to expose it also as an output; yet under the current implementation, it may actually make sense to also return the immediate state, for example as a third (optional) array output parameter, which would cover both use-cases with a single hook call (not requiring a setter or a second state hook). Of course, the alternative of turning initialState into state would require either adding a parameter (like onlyInitialState=true), or adding a new function with a new name, otherwise the forward compatibility would be threatened.

  • (Though it could be theoretically argued that users don't have too much motivation behind using non-constant initialValue - if they provide a variable solely because they can't afford having an empty state before calling a setter for the first time, as the input default isn't '', doesn't this mean it's already too late at the moment of hook usage, and they can supply the new state anyway? Also there's no way to immediately set an initial state at a later point, should the user prefer some lazy initialization).

Because I don't want to claim that one approach is better than the other one, I'd rather like to have the intended use-cases covered by the documentation, so that if there are some obvious situations where this implementation isn't supposed to fit in, you could at least direct new users to an alternative library. For now I'm assuming that you want to cover all of the basic debounce use-cases, considering the intention conveyed by the react-hook namespace :)

After click, clientX and clientY are not updating anymore

Hi,
After the update @3.0.2 now there is another problem, in the same sandbox

When you click the grey area, clientX and clientY are not updating anymore until you go out of the grey area and go in again, I saw the problem is the ref entered.current is true when you click (onDown) so it prevents onMove, maybe we should use separate ref for onDown?

Thanks again :)

google-optimize: Causes error when window.gtag is not defined

Hi! I use Google Optimize with Google Tag Manager which doesn't expose window.gtag function. When I attempt to use @react-hook/google-optimize it errors with window.gtag is not a function

Steps to reproduce the behavior:

  1. Setup React application with Google Tag Manager following the Quickstart Guide
  2. Use the useGoogleOptimize hook with any settings.
  3. Open the page.
  4. Application crashes with error: Uncaught TypeError: window.gtag is not a function

Expected behavior
I would expect no crash.

Additional context
I suspect the implementation is incomplete or tested only with the older Google Analytics script. Looking at the Optimize documentation mentioned in the source, there is this line as a kind of forward-compatibility shim:

// Not required if the Google Analytics gtag implementation is used.
function gtag() {dataLayer.push(arguments)}

Though I think this is outdated since even Analytics now recommend to use GTM by default.

I think the preferred change here is to use window.dataLayer directly but also check for its existence (there may be cases where the client is missing GTM and therefore dataLayer property, either through intentional blocking or network failure).

Support breakpoints in useWindowSize

I only care about whether my window width crosses a threshold from a CSS breakpoint, I don't need an update on every resize frame.

If I can build a hook for this using useWidthWidth, I'd love to know how!

function useIsWideWindow() {
  const width = useWindowWidth();
  return width > 1000;
}

we cant use optional refs in useMergeRef

I think it's better we can use optional ref, sometimes you want to get some optional ref from props so you cant use the current useMergeRef for this!

so change the refs argument to optional and use a filter before "for".

isOver is not working properly

Hi,

Thanks a lot for the great work.

There is an issue with isOver, I have created a sandbox to show you.

You'll see isOver initially is false but when you go in the grey div, it turns to true and will never go back to false (Unless you leave the grey area slowly), even clientX and clientY will not be null if the mouse doesn't leave the grey area slowly.

NOTE: You have to move the mouse out of the grey div quickly to reproduce.

IE 11 Support

Currently arrow functions need to be transpired by babel in order to support this in IE11.

Please use @babel/plugin-transform-arrow-functions.

useResizeObserver should observe `top`

Is your feature request related to a problem? Please describe.
I'm using the useResizeObserver to detect when various size properties change, including top.
For now, my useResizeObserver does not detect changes on top, so I don't get the final top value (once other components have settled)

Describe the solution you'd like
that useResizeObserver detects changes in the whole DOMRect, including top

Describe alternatives you've considered
For now, I have to avoid lazy loading so that all (actually most, all is impossible) components render at their final height. This is not a maintainable solution, and it doesn't always work. (some components have to wait for data before they size themselves)

Additional context
My use case:
I have many sections in my page.
I have a sticky on the right of the page, that should stay sticky until it reaches the top of Section12.
Section12's top is observed and stored
the sticky's container's height is defined using Section12's top value

My issue:
Section11 depends on remote data, so at first it's only a few px high. Then it takes about 900px.
Section12's top value computed with useResizeObserver is not updated when Section11 changes height (which changes the topvalue of Section12)

[useResizeObserver] Use border-box instead of content-box

Is your feature request related to a problem? Please describe.

getBoundingClientRect returns the border-box, which includes padding and borders. However by default ResizeObserver.observe uses the content-box, which does not. This renders the example for useResizeObserver incorrect as it'll set the size with padding, then update to the size without padding. useSize avoids this by using offsetWidth and offsetHeight.

Describe the solution you'd like

Either pass the content-box option to ResizeObserver.observe, or change the example in the README to not use getBoundingClientRect.

Describe alternatives you've considered
I just switched to reading offsetHeight like useSize does.

[size] Typo in `homepage`

Describe the bug
This is the current link: https://github.com/jaredLunde/react-hook/tree/master/packagess/#readme. It is 404.

To Reproduce
Steps to reproduce the behavior:

  1. Go to 'https://www.npmjs.com/package/@react-hook/size'
  2. Click on 'Homepage'
  3. See GitHub 404 page

Expected behavior
The link should probably be https://github.com/jaredLunde/react-hook/tree/master/packages/size#readme

Desktop (please complete the following information):
N/A

Smartphone (please complete the following information):
N/A

Additional context

Where is test coverage?

Is your feature request related to a problem? Please describe.
I tried to find tests for this awesome hooks but found snapshots only.

Describe the solution you'd like
Create test coverage for each hook

Incompatibility of resize-observer with Nextjs 12.

Describe the bug
We have updated our project to Next 12 and the following appears when we load a page with a component that uses resize-observer.
SyntaxError: The requested module 'react' is expected to be of type CommonJS, which does not support named exports. CommonJS modules can be imported by importing the default export. For example: import pkg from 'react'; const {useRef: r,useEffect: t}from"react";export default e=>{var a=r(e);return t(()=>{a.current=e}),a} = pkg;

To Reproduce
Steps to reproduce the behavior:

  1. Use resize-observer
  2. Update to Next 12

Screenshots
Screenshot 2021-12-31 at 09 17 15

Desktop (please complete the following information):

  • OS: MacOS
  • Browser: Chrome Version 96.0.4664.110
  • @react-hook/resize-observer Version: 1.2.5
  • next Version: 12.0.7

Where can I find packages changelogs?

Hello,

First, thanks a lot for these great hooks 😍

I am using some of them in a project. I am upgrading dependencies, and some hooks have new versions. I wanted to check what's new, but I couldn't find any changelogs. Do you generate some? If yes, where can I find them?

Thanks.

IE11 crashes with syntax error in the intersection-observer package

Describe the bug
The main bundle of the @react-hook/intersection-observer package uses arrow functions that makes IE11 crash with syntax error.

Example dist/main/index.js:

const useIntersectionObserver = (target, options = {}) => {
  //                                      ERROR HERE --^^
  const {
    root = null,
    pollInterval = null,
    useMutationObserver = false,
    rootMargin = '0px 0px 0px 0px',
    threshold = 0,
    initialIsIntersecting = false
  } = options;

  // ...
}

To Reproduce
Steps to reproduce the behavior:

  1. Load a page using this package in IE11, that is using the main package bundle.
  2. A syntax error is thrown.

Expected behavior
The main bundle should be transpiled to a version of JS that is supported by IE11.

Desktop (please complete the following information):

  • OS: Windows
  • Browser: IE
  • Version: 11

Looking for change log or why the breaking change (in window-size)?

I see the window-size bumped to version 3 in one of my projects. I struggle to find a change log, release information or migration instructions.

Can you please elaborate what was changed that might break projects using this dependency?

@react-hook/window-size latest 2.1.1 ❯ 3.0.6 https://github.com/jaredLunde/react-hook/tree/master/packages/window-size#readme

Thanks a bunch

[Mouse Position] on phone when there are elements in the scene is malfunctioning

Hi,

This one is a bit tough but I'll try to explain as much as I can.

after adding a child element to the grey area, somehow tracking the touch drag is interrupted.

bug

Steps to reproduce

In this sandbox toggle device toolbar from devTools in chrome and you'll see when you click and drag from bottom to top, somehow in the middle it stops tracking clientX and clientY or pageX, pageY even though I haven't released the mouse click.

Thank you in advance!

useHover does not work if the target element is rendered after the hook

Describe the bug
If the element accepting the target ref is not rendered untill after the hook has been initialised, the hover behaviour does not work.

To Reproduce

Click on the button to show the hover area. hover area becomes visible but does not change the hover state
https://codesandbox.io/s/react-hookhover-example-forked-rq54q?file=/src/App.js

Expected behavior
The hover area should trigger a change in the hover state, even if it is not renderered at the same time as the hook

[resize-observer] Multiple callbacks on a single html element

Is your feature request related to a problem? Please describe.
Unable to add multiple callbacks on a single HTML element. When I do useResizeObserver(target, callback); and target is the same on multiple components, only the latest callback will be called.

Describe the solution you'd like
useResizeObserver should not override existing callback on elements. So I propose changing callback map from Map<any, UseResizeObserverCallback> to Map<any, Array<UseResizeObserverCallback>>. Then changes subscribe and unsubscribe callback too. More on this on the PR

Describe alternatives you've considered
I have not considered other alternatives

Additional context
None

useMouse in Next.js init error

Code

import React, { useState, useEffect } from "react";
import useMouse from "@react-hook/mouse-position";

function Page({ ...props }) {
  const { screenX = 0, screenY = 0 } = useMouse(null, {
    fps: 30,
  });
  return (
    <div ></div>
  );
}

Error
image

useMediaQuery doesn't work on Safari IOS device

Describe the bug
I've been using the useMediaQuery perfectly in Edge, Chrome on a desktop, but no matter what the useMediaQuery("(max-width: 768px)") always returns false on Safari.

Any thoughts?

Here is the exact code running on an Iphone XS Max 14.X IOS

const isTabletOrLower = useMediaQuery('(max-width: 768px');

useMouse() returns the component's coordinates

Describe the bug
useMouse returns the component's x and y coordinates instead of the cursor positon.

To Reproduce
Steps to reproduce the behavior:

import * as React from 'react'
import useMouse from '@react-hook/mouse-position'

const Component = props => {
  const ref = React.useRef(null)
  const mouse = useMouse(ref, {
    enterDelay: 100,
    leaveDelay: 100,
  })

  return (
    // You must provide the ref to the element you're tracking the
    // mouse position of
    <div ref={ref}>
      Hover me and see where I am relative to the element:
      <br />
      x: ${mouse.x}
      y: ${mouse.y}
    </div>
  )
}

export default function App() {
  return <Component />
}

Expected behavior
Self explanatory, use the mouse position

Desktop (please complete the following information):

  • OS: macOS 12.0.1
  • Browser Chrome, Brave
  • Version:
    • react: ^17.0.2
    • @react-hook/mouse-position: ^4.1.1

Add `useLocalStorage`

Is your feature request related to a problem? Please describe.
I ofen re-write the same code around a state value which should be stored across tabs / sessions

Describe the solution you'd like
a useLocalStorage hook which would function the same way as useState

Describe alternatives you've considered
n/a

Additional context
If you're ok w/ the idea, I can send a PR with this code:

import React from "react";

const loadStorage = (key, defaultValue) => {
  if (typeof window === "undefined") return defaultValue;

  try {
    const item = localStorage.getItem(key);
    if (item == null) return defaultValue;
    return JSON.parse(localStorage.getItem(key));
  } catch (err) {
    return defaultValue;
  }
};

export default function useLocalStorage(key, initialValue) {
  const [defaultValue] = React.useState(initialValue);

  const [value, setValue] = React.useState(() =>
    loadStorage(key, defaultValue)
  );

  const setStorageValue = React.useCallback(
    (update) => {
      setValue((current) => {
        const newValue = update instanceof Function ? update(current) : update;

        localStorage.setItem(key, JSON.stringify(newValue));
        window.dispatchEvent(new Event(`localStorageUpdate::${key}`));

        return newValue;
      });
    },
    [key]
  );

  React.useEffect(() => {
    const listener = (e) => setValue(loadStorage(key, defaultValue));

    window.addEventListener("storage", listener);
    window.addEventListener(`localStorageUpdate::${key}`, listener);

    return () => {
      window.removeEventListener("storage", listener);
      window.removeEventListener(`localStorageUpdate::${key}`, listener);
    };
  }, [key, defaultValue]);

  return [value, setStorageValue];
}

[hotkey] not possible to create hotkey for [mod, +]

Trying to implement zoom behaviour in a app, and want to use standard keybindings:

CMD + 0 -- zoom to 100%
CMD + - -- zoom out
CMD + + -- zoom in

I cannot create one for zooming in because of the lack of "+".

useSize initialWidth and initialHeight types

Describe the bug
The UseSizeOptions interface defines the parameters initialHeight and initialWidth as type 0 instead of number. This makes TypeScript complain when trying to specify a value different from 0.

To Reproduce
Steps to reproduce the behavior:

  1. Instantiate a useSize hook
  2. Pass a configuration object specifying initialHeight and/or initialWidth with values != 0
  3. See TypeScript errors

Expected behavior
The type of initialHeight and initialWidth should be number.

Desktop (please complete the following information):

  • OS: macOS Big Sur
  • Browser: Chrome
  • Version: 2.1.0

Additional context
I can submit a PR to fix this.

The useSize() demo for resize-observer doesn't capture element's initial size

Describe the bug
The useSize() function in the demo for @react-hook/resize-observer uses the anti-pattern of depending on the ref object provided by React.useRef() in the dependency list of React.useLayoutEffect(). This has the effect of not setting an initial value for the size on the first rendering. This matters because elements that don't get re-rendered never get a sized.

To Reproduce
Use the size

Expected behavior
Get a size for elements on the first time they are rendered.

Additional context
Depending on the node itself via useState instead of the ref (which is never updated and therefor never calls) is the usual work around

export function useSize(): {
    ref: (node: HTMLDivElement | null) => void
    size: DOMRect | undefined
} {
    const [size, setSize] = useState<DOMRect | undefined>()
    const [node, ref] = useState<HTMLElement | null>(null)

    useLayoutEffect(() => {
        node !== null && setSize(node.getBoundingClientRect())
    }, [node])

    // Where the magic happens
    useResizeObserver(node, (entry) => {
        setSize(entry.contentRect)
    })

    return { ref, size } // this is also a little wierd since ref isn't a ref object but a setter function, but works if using it in the context of <div ref={ref}>
}

I don't think native ResizeObserver is ever used

Looking at https://github.com/jaredLunde/react-hook/blob/master/packages/resize-observer/src/index.tsx

It seems you are using https://github.com/juggle/resize-observer

According to their docs, they expect the user to detect if window.ResizeObserver exists themselves, and use the polyfill if it doesn't.

This will use the ponyfilled version of ResizeObserver, even if the browser supports ResizeObserver natively.

Seems like the native ResizeObserver will never be used.

[resize-observer, size] Replace unmaintained resize-observer-polyfill with @juggle/resize-observer

Is your feature request related to a problem? Please describe.
The useResizeObserver and useSize hooks use resize-observer-polyfill which hasn't been updated in 3 years and has a really annoying issue with its types since TS 4.2. This is causing many users to stick to TS 4.1 in the hopes of a new release of resize-observer-polyfill but the owner hasn't responded in months.

See que-etc/resize-observer-polyfill#80 and que-etc/resize-observer-polyfill#83 for additional information.

Describe the solution you'd like
Use @juggle/resize-observer instead of resize-observer-polyfill as a drop-in replacement for @react-hook/size and @react-hook/resize-observer.

Describe alternatives you've considered
None.

Additional context
I can try creating a PR if this change is wanted. Please let me know which versions of IE need to be supported as @juggle/resize-observer needs additional polyfills for IE9/IE10 but supports IE11 out of the box.

More documentation about how to install Google Optimize

Is your feature request related to a problem? Please describe.
It is unclear about what needs to be installed to get this library to work.

The docs mention

Using the useGoogleOptimize hook requires that you've installed Google Tag Manager and created Google Optimize test cases.

But clicking that link, there is note that says to use the Optimize js install:

We strongly recommend using the optimize.js installation method as it offers the best performance and is the easiest way to install Optimize.

So what do I need to install to get this to work? GTM or Optimize or both?

Describe the solution you'd like
Please update documentation on readme to describe how to get this working as it appear the linked documentation may have changed without knowing.

Describe alternatives you've considered
N/A

Additional context
N/A

useMouse()

OnMove/onTouchMove function under mouse.tsx got error for element variable with Type 'T|RefObject ' is not assignable to type T. n the line of 'dispatch({type: 'mousemove', event, element}))'

Please help to resolve the issue. I just get the src code and work on top of it without using npm compiled package.

Does useMediaQuery optimize multiple calls?

Hello!

Thank you for this great library!

However, when you have a lot of components that call useMediaQuery() with the same attributes does it optimize such calls somehow?

The use-media library has a recommendation regarding the context usage to optimize such calls. Is it required with useMediaQuery()?

Thanks!

[Types] IntersectionObserverOptions.threshold prevents number[]

Hi there, observed the following inconsistency:

Describe the bug
According to the documentation IntersectionObserverOptions.threshold can be either number | number[].
But the types only allow for type number.

To Reproduce
Steps to reproduce the behavior:

  1. Call const test = useIntersectionObserver(null, {threshold: [0, 1]})
  2. See error Type 'number[]' is not assignable to type 'number'.ts(2322)

Expected behavior
The options object should accept type number[]

Would you be open for a PR?

useWindowScroll.removeEventListener()

Could you provide a method to clean up/destroy the event listener for useWindowScroll?

After I've used it, I no longer want the event listener to run and I should be able to clean up.

For example:

function MyComponent() {
	const { scrollY, cleanUp } = useWindowScroll();
	const [showMessage, setShowMessage] = useState(false);

	useEffect(() => {
		if (scrollY > 300) {
			setShowMessage(true);
			cleanUp();
		}
	}, [scrollY]);

	return (
		<div>{showMessage ? "You've scrolled far enough!" : 'Keep scrolling'}</div>
	);
}

useMouse() option to keep last value when out of element?

Is your feature request related to a problem? Please describe.
I've got an application where some divs will resize to follow the mouse. Currently the divs retreat back to 0 when exiting the available area, would be nice to have an option where they could stay at the last value before the mouse left the area. Especially for touch devices.

Describe the solution you'd like
I would like it if there was a mouseoption I could pass, which means that after the mouse (or touch) exits the reference area, the mouse position remains at the last recorded location, rather than becoming null.

Describe alternatives you've considered
I wondered about whether I could have some state which is updated by useMouse(), or whether your useLatest() hook can do it somehow, but I haven't managed to figure that out. If there is an alternative, please do let me know

Additional context
I've not got much additional context really.

Side note: the main readme lists this hook as useMousePosition(), but the hook is useMouse()

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.