Categories
React Hooks

Top React Hooks — Network, Long Press, and Scrolling

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 useNetwork hook lets us detect the network type.

To us it, we can write:

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

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

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

We call the useNetwork hook to return the network state.

The returned object has the online , downlink , effectiveType and rtt properties.

online has the online status.

downlink has internet downlink.

effectiveType has the effective network type.

rtt has the round trip delay.

The useOrientation hook lets us track the screen orientation of the user’s device.

To use it, we write:

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

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

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

We use the useOrientation hook to return an object with the orientation data.

Then object has the angle , which is the angle of the screen.

It also has the type property, which is the screen orientation.

The usePageLeave hook lets us run a callback when the mouse leaves the page.

For instance, we can write:

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

export default function App() {
  usePageLeave(() => console.log("left page"));

  return <></>;
}

The hook takes a callback that runs when our mouse leaves the page.

The useStartTyping hook lets us detect when we start typing.

It takes a callback that runs when we start typing.

For example, we can write:

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

export default function App() {
  useStartTyping(() => console.log("Started typing"));

  return null;
}

The useWindowScroll hook lets us rerender on window scroll.

For example, we can write:

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

export default function App() {
  const { x, y } = useWindowScroll();

  return (
    <div>
      <div style={{ position: "fixed" }}>
        x: {x} y: {y}
      </div>
      {Array(1000)
        .fill()
        .map((_, i) => (
          <p key={i}>{i}</p>
        ))}
    </div>
  );
}

We have the useWindowScroll hook that returns the x and y coordinates of the scrolling.

The useScroll hook lets us watch for the scrolling of an element.

To use it, we can write:

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

export default function App() {
  const scrollRef = React.useRef(null);
  const { x, y } = useScroll(scrollRef);

  return (
    <div ref={scrollRef} style={{ overflow: "scroll", height: 300 }}>
      <div style={{ position: "fixed" }}>
        x: {x} y: {y}
      </div>
      {Array(1000)
        .fill()
        .map((_, i) => (
          <p key={i}>{i}</p>
        ))}
    </div>
  );
}

We created a ref and pass that into the element that we want to watch the scrolling for.

We’ve to set the overflow style so that we scroll the element when there’s overflowing content.

Conclusion

The react-use package has hooks to listening to scrolling on the window and elements.

Also, we can watch for key presses.

Categories
React Hooks

Top React Hooks — Memoization and Previous Value

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.

createMemo

The createMemo function creates a hook that has the state memoized.

Ir takes a function that returns a state.

For instance, we can write:

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

const product = n => {
  let result = 1;
  for (let i = 1; i <= n; i++) {
    result *= i;
  }
  return result;
};

const useMemoProduct = createMemo(product);

export default function App() {
  const result = useMemoProduct(9);

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

We have the product function which returns the product of n numbers multiplied together.

And we pass that into the createMemo function to return the useMemoProduct hook.

The hook takes the same arguments as the product function.

The hook returns the result which is the same as the product function.

Then we render the result in App .

useGetSetState

The useGetSetState hook lets us get and set the state, where the state may be an object.

To use it, we can write:

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

export default function App() {
  const [get, setState] = useGetSetState({ count: 0 });
  const onClick = () => {
    setState({ count: get().count + 1 });
  };

  return <button onClick={onClick}>Clicked: {get().count}</button>;
}

We call the useGetSetState with an argument being the initial value.

It returns the get function to get the state value.

The setState the function sets the state.

Then we can call get to get the count property’s value.

usePrevious

We can get the previous value of a state with the usePrevious hook.

For instance, we can write:

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

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

  return (
    <p>
      <button onClick={() => setCount(count + 1)}>increment</button>
      <button onClick={() => setCount(count - 1)}>decrement</button>
      <p>
        Now: {count}, before: {prevCount}
      </p>
    </p>
  );
}

We use the useState hook to return a state getter and setter function.

Then we pass the state into the usePrevious hook.

And then we get the current and previous value of count with count and prevCount respectively.

usePreviousDistinct

The usePreviousDistinct hook is like usePrevious , but the value updates only when the value actually changes.

This lets us get the previous distinct value instead of the previous value.

For instance, we can write:

import React from "react";
import { usePreviousDistinct, useCounter } from "react-use";

export default function App() {
  const [count, { inc: relatedInc }] = useCounter(0);
  const [anotherCount, { inc }] = useCounter(0);
  const prevCount = usePreviousDistinct(count);

  return (
    <p>
      Count: {count}, before count: {prevCount}
      <button onClick={() => relatedInc()}>Increment</button>
      Another count: {anotherCount}
      <button onClick={() => inc()}>Increment Unrelated</button>
    </p>
  );
}

We created 2 number states, count and anotherCount .

Then we use the increment functions that are returned with them.

And we pass the count into the usePreviousDistinct hook.

Conclusion

The react-use library lets us memoize results, get the previous value, and more with its hooks.

Categories
React Hooks

Top React Hooks — Long Press and Mouse Position

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 useLongPress hook lets us detect long presses of a key.

To use it, we can write:

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

export default function App() {
  const onLongPress = () => {
    console.log("long pressed");
  };

  const defaultOptions = {
    isPreventDefault: true,
    delay: 300
  };
  const longPressEvent = useLongPress(onLongPress, defaultOptions);

  return <button {...longPressEvent}>long press me</button>;
}

We have the useLongPress hook that takes a callback to run when the button us long pressed.

defaultOptions has the options for the hook.

isPreventDefault lets us prevent the default action.

delay is the delay before running the callback.

We pass the object that’s returned by the hook to the button.

The longPressEvent object has various event handlers, including onMouseDown , onTouchStart , onMouseUp , onMouseLeave and onTouchEnd .

The useMedia hook lets us detect the given media query in our React component.

To use it, we run:

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

export default function App() {
  const isWide = useMedia("(min-width: 400px)");

  return <div>Screen is wide: {isWide ? "Yes" : "No"}</div>;
}

We use the useMedia hook with the media query we want to watch for in our component.

It returns a boolean that indicates whether the given media query is matched.

The useMediaDevices hook lets us track connected hardware devices.

For instance, we can use it by writing:

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

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

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

The useMediaDevices hook returns an object with the devices property, which has the deviceId , groupId , kind , and label properties.

kind has the hardware type.

The useMotion hook lets us detect motion with the acceleration sensor.

For instance, we can write:

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

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

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

We have the useMotion hook to return the data from the accelerometer.

It includes the acceleration , accelerationIncludingGravity , rotationRate , and interval .

They give us the acceleration and rotation rate of our device.

The useMouse lets us re-render on mouse position changes.

For instance, we can use it by writing:

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

export default function App() {
  const ref = React.useRef(null);
  const mouseLocation = useMouse(ref);

  return (
    <div ref={ref}>
      <div>{JSON.stringify(mouseLocation)}</div>
    </div>
  );
}

The useMouse hook takes a ref for the element that we want to watch the mouse position for.

docX and docY has the mouse position in the whole document.

posX and posY has the position in the element.

elX and elY has the mouse position in the element.

elH and elW has the height and width of the element.

Conclusion

react-use has hooks to detect long mouse presses and mouse positions.

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.