Preact — Side Effect Hooks

John Au-Yeung - Jan 22 '21 - - Dev Community

Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62

Subscribe to my email list now at http://jauyeung.net/subscribe/

Preact is a front end web framework that’s similar to React.

It’s smaller and less complex than React.

In this article, we’ll look at how to get started with front end development with Preact.

useEffect

We use the useEffect hook to commit side effects.

For example, we can write:

import { render } from "preact";
import { useEffect } from "preact/hooks";

function PageTitle({ title }) {
  useEffect(() => {
    document.title = title;
  }, [title]);

  return <h1>{title}</h1>;
}

export default function App() {
  return (
    <div>
      <PageTitle title="hello world" />
    </div>
  );
}
if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}
Enter fullscreen mode Exit fullscreen mode

We have the PageTitle component which takes the title prop.

Then we can watch the value of that with the useEffect hook’s 2nd argument.

And we set the document.title to the title prop’s value.

We can also use it to listen to events when we mount the component and unbind the event handler when we unmount it.

For example, we can write:

import { render } from "preact";
import { useEffect, useState } from "preact/hooks";

export default function App() {
  const [width, setWidth] = useState(0);

  function onResize() {
    setWidth(window.innerWidth);
  }

  useEffect(() => {
    window.addEventListener("resize", onResize);
    return () => window.removeEventListener("resize", onResize);
  }, []);

  return <div>Window width: {width}</div>;
}
if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}
Enter fullscreen mode Exit fullscreen mode

We have the width state to set the window’s width.

onResize calls setWidth to set the width.

In the useEffect hook, we call window.addEventListener to listen to the resize event.

And we return the callback to remove the listener when we unmount the component.

Then we show the width in the div .

Now when we resize the window, we’ll see the width number change.

useLayoutEffect

useLayoutEffect has the same signature as useEffect , but it’ll fire as soon as the component is diffed and the browser has a chance to paint.

useErrorBoundary

The useErrorBoundary hook lets us catch errors when a child component throws an error.

Then we can catch them with this hook.

For example, we can write:

import { render } from "preact";
import { useErrorBoundary } from "preact/hooks";

const Child = () => {
  if (Math.random() < 0.5) {
    throw new Error("error");
  }
  return <p>child</p>;
};

const Parent = ({ children }) => {
  const [error, resetError] = useErrorBoundary();

  if (error) {
    return (
      <div>
        <p>{error.message}</p>
        <button onClick={resetError}>Try again</button>
      </div>
    );
  } else {
    return <div>{children}</div>;
  }
};

export default function App() {
  return (
    <div>
      <Parent>
        <Child />
      </Parent>
    </div>
  );
}
if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}
Enter fullscreen mode Exit fullscreen mode

We have the Child component that randomly throws an error.

And we have the Parent component that renders child components if there’s no error thrown in child components.

If there’re errors throw in child components, then we show the error and show a button to run the resetError function when we click it.

resetError remounts the component.

So when we when an error raised in Child , we can click Try Again to refresh the child components.

Conclusion

We can use the useEffect hook to commit side effects.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .