Categories
React Hooks

Top React Hooks — Lock Scrolling, Animation Loop, Session Storage, and Throttling

Hooks contains our logic code in our React app.

We can create our own hooks and use hooks provided by other people.

In this article, we’ll look at some useful React hooks.

react-use

The react-use library is a big library with many handy hooks.

useLockBodyScroll

The useLockBodyScroll hook lets us lock the scrolling of the body element.

It’s useful for modals and overlays.

It takes an argument to let us lock scrolling or not.

For example, we can write:

import React from "react";
import { useLockBodyScroll, useToggle } from "react-use";

export default function App() {
  const [locked, toggleLocked] = useToggle(false);

  useLockBodyScroll(locked);

  return (
    <div>
      <button onClick={() => toggleLocked()}>
        {locked ? "Unlock" : "Lock"}
      </button>
      {Array(1000)
        .fill()
        .map((_, i) => (
          <p>{i}</p>
        ))}
    </div>
  );
}

We have a button to toggle the locked state.

If it’s true , we disable locking scrolling on the body.

Otherwise, we let users scroll the body.

useRafLoop

The useRafLoop hook lets us run the requestAnimationFrame loop without re-rendering the parent component.

The loop stops automatically on component unmount.

For instance, we can write:

import React from "react";
import { useRafLoop, useUpdate } from "react-use";

export default function App() {
  const [ticks, setTicks] = React.useState(0);
  const [lastCall, setLastCall] = React.useState(0);
  const update = useUpdate();

  const [loopStop, loopStart, isActive] = useRafLoop(time => {
    setTicks(ticks => ticks + 1);
    setLastCall(time);
  });

  return (
    <div>
      <div>RAF triggered: {ticks} (times)</div>
      <div>Last high res timestamp: {lastCall}</div>
      <br />
      <button
        onClick={() => {
          isActive() ? loopStop() : loopStart();
          update();
        }}
      >
        {isActive() ? "stop" : "start"}
      </button>
    </div>
  );
}

We use the useRafLoop hook by passing in callback with the time , which is the timestamp since the loop started.

The timestamp is in milliseconds.

It returns an array with the loopStop , loopStart and isActive variables.

loopStop lets us stop the requestAnimationFrame loop.

loopStart lets us start the requestAnimationFrame loop.

isActive is true when the requestAnimationFrame loop is active.

useSessionStorage

The useSessionStorage hook lets us manage our browser’s session storage.

To use it, we write:

import React from "react";
import { useSessionStorage } from "react-use";

export default function App() {
  const [value, setValue] = useSessionStorage("session-key", "foo");

  return (
    <div>
      <div>Value: {value}</div>
      <button onClick={() => setValue("qux")}>qux</button>
      <button onClick={() => setValue("baz")}>baz</button>
    </div>
  );
}

The useSessionStorage hook takes the key for the session storage as the first argument.

The 2nd argument is the value for the given key.

It returns the value and setValue variables to let us get and set the value respectively.

useThrottle

We can use the useThrottle hook to throttle the value updates.

To use it, we can write:

import React from "react";
import { useThrottle } from "react-use";

export default function App() {
  const [value, setValue] = React.useState(0);
  const throttledValue = useThrottle(value, 1000);

  return (
    <>
      <button onClick={() => setValue(c => c + 1)}>increment</button>
      <div>Value: {value}</div>
      <div>Throttled value: {throttledValue}</div>
    </>
  );
}

We call the useThrottle hook, which takes the state value and the number of milliseconds to delay the updates.

Then we render both the unthrottled and throttled values.

Conclusion

We can throttle state updates, lock scrolling, run the requestAnimationFrame loop, and manage session storage with the react-use library.

Categories
React Hooks

Top React Hooks — Lifecycle Hooks

Hooks contains our logic code in our React app.

We can create our own hooks and use hooks provided by other people.

In this article, we’ll look at some useful React hooks.

react-use

The react-use library is a big library with many handy hooks.

useMountedState

The useMountedState hook lets us check a component’s mount state.

It returns a function that returns true is it’s mounted and false if it’s not.

For instance, we can write:

import React from "react";
import { useMountedState } from "react-use";

export default function App() {
  const isMounted = useMountedState();

  return <div>{isMounted() ? "mounted" : "not mounted"}</div>;
}

We can just use the returned value to check if the component is mounted.

useUnmountPromise

The useUnmountPromise hook lets us check the mounted state with a promise.

The promise doesn’t resolve if the component unmounts.

For instance, we can write:

import React from "react";
import useUnmountPromise from "react-use/lib/useUnmountPromise";

export default function App() {
  const mounted = useUnmountPromise();

  const callback = async () => {
    await mounted(Promise.resolve(1));
  };

  React.useEffect(callback, []);

  return <div />;
}

We pass in a promise to the mounted function that runs when the component is mounted.

It also takes an error callback than runs when the component is unmounted.

usePromise

The usePromise hook returns a helper function that wraps promises.

Promises in the function only resolves when the component is mounted.

For instance, we can write:

import React from "react";
import { usePromise } from "react-use";

export default function App() {
  const mounted = usePromise();
  const [value, setValue] = React.useState();

  const onMount = async () => {
    const value = await mounted(Promise.resolve(1));
    setValue(value);
  };

  React.useEffect(() => {
    onMount();
  });

  return <div>{value}</div>;
}

We call the usePromise hook to return the mounted function.

The mounted function takes a promise and returns a promise that resolves to the value of the promise we passed to it.

Then we can use the resolved value however we like.

useLogger

The useLogger lets us logs component transitions.

To use it, we can write:

import React from "react";
import { useLogger } from "react-use";

const Counter = props => {
  useLogger("Counter", props);
  return props.count;
};

export default function App() {
  const [count, setCount] = React.useState(0);

  return (
    <div>
      <button onClick={() => setCount(c => c + 1)}>increment</button>
      <p>
        <Counter count={count} />
      </p>
    </div>
  );
}

We have the Counter prop that has the useLogger hook.

It takes the props from the component and logs it.

Then when we pass values to the count prop, they’ll all be logged.

useMount

The useMount hook lets us call a function after the component is mounted.

To use it, we can write:

import React from "react";
import { useMount } from "react-use";

export default function App() {
  useMount(() => console.log("mounted"));

 return <div />;
}

to use it.

We just pass in a callback that runs when the component is mounted.

Conclusion

The react-use library provides us with lifecycle hooks for running code on mount, unmount, and log the values.

Categories
React Hooks

Top React Hooks — Keypresses and Intersection

Hooks contains our logic code in our React app.

We can create our own hooks and use hooks provided by other people.

In this article, we’ll look at some useful React hooks.

react-use

The react-use library is a big library with many handy hooks.

We can use the useIntersection hook to detect whether an element is obscured or fully in view.

To use it, we can write:

import React from "react";
import { useIntersection } from "react-use";

export default function App() {
  const intersectionRef = React.useRef(null);
  const intersection = useIntersection(intersectionRef, {
    root: null,
    rootMargin: "0px",
    threshold: 1
  });

  return (
    <>
      {Array(50)
        .fill()
        .map((_, i) => (
          <p>{i}</p>
        ))}
      <div ref={intersectionRef}>
        {intersection && intersection.intersectionRatio < 1
          ? "Obscured"
          : "Fully in view"}
        <p>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit. In varius
          nisl quis nibh laoreet, vitae feugiat nisi maximus. Nullam vitae mi
          magna. Fusce lorem lacus,
        </p>
      </div>
    </>
  );
}

We created a ref that we pass into the useIntersection hook and the element that we want to watch.

The hook takes a few options.

root is the root element.

rootMargin is the margin of the root.

threshold is the threshold to determine whether the intersection exists.

The useKey hook lets us run a handler when a keyboard key is pressed.

For instance, we can write:

import React from "react";
import { useKey } from "react-use";

export default function App() {
  const [count, set] = React.useState(0);
  const increment = () => set(count => count + 1);
  useKey("ArrowDown", increment);

  return <div>Press arrow down: {count}</div>;
}

We use the useKey hook with the string with the key name and the function to run when the key is pressed.

It’s also available as a render prop.

To use it, we write:

import React from "react";
import UseKey from "react-use/lib/comps/UseKey";

export default function App() {
  const [count, set] = React.useState(0);
  const increment = () => set(count => count + 1);

  return (
    <>
      <UseKey filter="ArrowDown" fn={increment} />
      <div>Press arrow down: {count}</div>
    </>
  );
}

We used the UseKey component with the filter and fn props.

filter has the key name.

fn has the function to run when the key is pressed.

We can also use the useKey hook with a predicate:

import React from "react";
import { useKey } from "react-use";

export default function App() {
  const [count, set] = React.useState(0);
  const increment = () => set(count => count + 1);

  const predicate = event => event.key === "ArrowDown";
  useKey(predicate, increment, { event: "keyup" });

  return (
    <>
      <div>Press arrow down: {count}</div>
    </>
  );
}

We have the predicate function to check the key property with the string of the key name.

We pass that into the useKey hook with the object with the event name.

The useKeyPress hook lets us listen for key presses.

For instance, we can write:

import React from "react";
import { useKeyPress } from "react-use";
const keys = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"];

export default function App() {
  const states = [];
  for (const key of keys) states.push(useKeyPress(key)[0]);

  return (
    <div>
      Try pressing numbers
      <br />
      {states.join(", ")}
    </div>
  );
}

We have the useKeyPress hook with the argument being the key name.

This will let us detect whether the given key is pressed.

It returns an array with the first entry being true if the key is pressed.

Conclusion

The react-use package has hooks to detect key presses and detect intersections.

Categories
React Hooks

Top React Hooks — Keyboard and Query Strings

Hooks contains our logic code in our React app.

We can create our own hooks and use hooks provided by other people.

In this article, we’ll look at some useful React hooks.

react-use

The react-use library is a big library with many handy hooks.

The useKeyboardJs hook lets us detect key combo presses.

For instance, we can write:

import React from "react";
import useKeyboardJs from "react-use/lib/useKeyboardJs";

export default function App() {
  const [isPressed] = useKeyboardJs("a + b");

  return <div>[a + b] pressed: {isPressed ? "Yes" : "No"}</div>;
}

We also need to install the keyboardjs package for this hook to work.

To use the hook, we just pass in the string.

And it returns an array with the first entry being the key combo that’s pressed.

Then when we press both keys a and b, we’ll show ‘Yes’.

The useKeyPressEvent hook fires both keydown and keyup callbacks.

But it only triggers each callback once per press cycle.

It’ll fire the keydown callback only once if we press and hold a key.

For instance, we can use it by writing:

import React from "react";
import { useKeyPressEvent } from "react-use";

export default function App() {
  const [count, setCount] = React.useState(0);

  const increment = () => setCount(count => count + 1);
  const decrement = () => setCount(count => count - 1);
  const reset = () => setCount(count => 0);

  useKeyPressEvent("[", increment, increment);
  useKeyPressEvent("]", decrement, decrement);
  useKeyPressEvent("r", reset);

  return (
    <div>
      <p>Count: {count}</p>
    </div>
  );
}

We create the functions increment , decrement , and reset to change the count state.

The useKeyPressEvent hook lets us listen to key presses.

The first argument is the key.

The 2nd and 3rd arguments are the callbacks that run when the key is down and up.

The useLocation hook lets us track the browser’s location.

We need to install the Geolocation API polyfill for IE to support IE.

To use it, we write:

import React from "react";
import { useLocation } from "react-use";

export default function App() {
  const state = useLocation();

  return <pre>{JSON.stringify(state, null, 2)}</pre>;
}

We have various properties like in the state like trigger , state m hash , host , hostname , etc.

hash hash the URL segment after the pound sign.

hostname has the hostname.

href has the whole URL.

origin has the root URL segment.

port has the port.

pathname has the pathname without the root part.

protocol has the protocol that we communicate through.

search has the query string.

The useSearchParam hook lets us track location search params.

For instance, we can use it by writing:

import React from "react";
import { useSearchParam } from "react-use";

export default function App() {
  const foo = useSearchParam("foo");

  return (
    <>
      <div>
        <button
          onClick={() =>
            history.pushState({}, "", `${location.pathname}?foo=123`)
          }
        >
          123
        </button>
        <button
          onClick={() =>
            history.pushState({}, "", `${location.pathname}?foo=456`)
          }
        >
          456
        </button>
        <button
          onClick={() =>
            history.pushState({}, "", `${location.pathname}?foo=789`)
          }
        >
          789
        </button>
        <p>{foo}</p>
      </div>
    </>
  );
}

In each button, we called pushState to go to a URL with different query strings.

The useSearchParam hook takes the key of the query string to get the value of and returns the value.

Then we’ll see the return value rendered.

Conclusion

The react-use package has hooks to detect key presses and query strings.

Categories
React Hooks

Top React Hooks — Idleness, Geolocation, and Hashes

Hooks contains our logic code in our React app.

We can create our own hooks and use hooks provided by other people.

In this article, we’ll look at some useful React hooks.

react-use

The react-use library is a big library with many handy hooks.

The useGeolocation hook lets us get the location data within our React app.

We can use it by writing:

import React from "react";
import { useGeolocation } from "react-use";

export default function App() {
  const state = useGeolocation();

  return <>{JSON.stringify(state)}</>;
}

We use the useGeolocation to get various pieces of data.

It includes the accuracy, latitude, longitude, altitude, speed, and loading state.

The useHover and useHoverDirty gooks lets us watch for hovering of an element.

To use the useHover hook, we can write:

import React from "react";
import { useHover } from "react-use";

export default function App() {
  const element = hovered => <div>Hover me {hovered.toString()}</div>;
  const [hoverable, hovered] = useHover(element);

  return (
    <div>
      {hoverable}
      <div>{hovered.toString()}</div>
    </div>
  );
}

We use the useHover hook with the element of our choice.

The element is a function that takes the hovered parameter and returns some elements.

useHover returns an array with the hoverable and hovered variables.

hoverable indicates whether an element is hoverable.

hovered indicates whether the element is hovered on.

useHover uses onMouseEnter and onMouseLeave to watch for hovering.

useHoverDirty accept a React ref.

And it sets its handlers to the onmouseover and onmouseout properties.

To use it, we write:

import React from "react";
import { useHoverDirty } from "react-use";

export default function App() {
  const ref = React.useRef();
  const isHovering = useHoverDirty(ref);

  return (
    <div ref={ref}>
      <div>{isHovering.toString()}</div>
    </div>
  );
}

useHoverDirty takes a ref, which we also pass to the element we want to watch hover on.

It returns the isHovering variable which indicates whether we’re hovering on it or not.

useHash is a hook that tracks the browser location’s hash.

To use it, we can write:

import React from "react";
import { useHash, useMount } from "react-use";

export default function App() {
  const [hash, setHash] = useHash();

  useMount(() => {
    setHash("#/foo/page?userId=123");
  });

  return (
    <div>
      <div>
        <pre>{window.location.href}</pre>
      </div>
      <div>Edit hash: </div>
      <div>
        <input
          style={{ width: "100%" }}
          value={hash}
          onChange={e => setHash(e.target.value)}
        />
      </div>
    </div>
  );
}

to use it.

We use the useMount hook which changes the hash when the component mounts.

We did that with the setHash function returned by the useHash hook.

hash has the hash value with the pound sign.

When we get the window.location.href , we’ll get the whole URL with the hash.

The useIdle hook let us determine if the page id idle.

To use it, we write:

import React from "react";
import { useIdle } from "react-use";

export default function App() {
  const isIdle = useIdle(1000);

  return (
    <div>
      <div>User is idle: {isIdle ? "yes" : "no"}</div>
    </div>
  );
}

We use the useIdle hook with the time to idle in milliseconds in the argument.

It returns the isIdle boolean variable to indicate whether the page is idle or not.

Conclusion

The react-use package comes with many useful hooks like geolocation, watching hovering, and watching for idleness.