Categories
Preact

Preact — Side Effect Hooks

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"));
}

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"));
}

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"));
}

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.

Categories
Preact

Preact — Memoization, Callbacks, and Context Hooks

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.

Memoization

We can use the useMemo hook to store results of expensive computations.

For example, we can write:

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

const expensive = (a, b) => {
  //...
};

function App() {
  const [a, setA] = useState(0);
  const [b, setB] = useState(0);
  const memoized = useMemo(() => expensive(a, b), [a, b]);
  //...
  return (
    <div>
      <p>{memoized}</p>
    </div>
  );
}

if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}

We have the expensive function that does some expensive operation.

We call it in the useMemo callback to cache its result.

memoized is only computed again when a or b is changed.

We shouldn’t commit any side effects in useMemo .

If we need to commit side effects, we should use useEffect .

useCallback

The useCallback hook lets us ensure that the returned function is referentially equal until the dependencies change.

For example, we can write:

import { render } from "preact";
import { useCallback, useState } from "preact/hooks";
function App() {
  const [count, setCount] = useState(0);
  const increment = () => setCount(count + 1);
  const decrement = () => setCount((currentCount) => currentCount - 1);

  const log = useCallback(() => console.log(count), [count]);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={log}>log</button>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </div>
  );
}
if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}

We pass in a callback into the useCallback hook to cache the callback until the count state changes.

This lets us prevent the callback from recreated every time the component renders.

useRef

The useRef hook lets us get a reference to a DOM node in a function component.

For instance, we can write:

import { render, Fragment } from "preact";
import { useRef } from "preact/hooks";

function App() {
  const input = useRef(null);
  const onClick = () => input.current && input.current.focus();

  return (
    <>
      <input ref={input} />
      <button onClick={onClick}>Focus input</button>
    </>
  );
}
if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}

We call the useRef hook to return a ref.

Then we assign it to the input with the ref prop.

We also create the onClick function to get the input element with the input.current property and call focus on it.

So when we click on Focus Input, the input will be focused.

useContext

The useContext hook lets us access a context in a function component.

For example, we can write:

import { createContext, render, Fragment } from "preact";
import { useContext } from "preact/hooks";

const Theme = createContext("light");

function DisplayTheme() {
  const theme = useContext(Theme);
  return <p>Active theme: {theme}</p>;
}

function SomeComponent({ children }) {
  return <>{children}</>;
}

export default function App() {
  return (
    <div>
      <Theme.Provider value="dark">
        <SomeComponent>
          <DisplayTheme />
        </SomeComponent>
      </Theme.Provider>
    </div>
  );
}

if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}

We call createContext to create the Theme context.

Then we render the Theme.Provider in app to set the value of the context.

And we can get the Theme context value with the useContext hook in the DisplayTheme component.

We pass in the context that we want to access.

If our component is inside the Theme.Provider then we can access its value.

Conclusion

We can use hooks to memorize data, cache callbacks, and share data between components with Preact.

Categories
Preact

Preact — Hooks

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.

Hooks

Preact comes with hooks just like React.

We can use them to set states and commit side effects.

For example, we can use them by writing:

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

function useCounter() {
  const [value, setValue] = useState(0);
  const increment = useCallback(() => {
    setValue(value + 1);
  }, [value]);
  return { value, increment };
}

function App() {
  const { value, increment } = useCounter();
  return (
    <div>
      <p>Counter {value}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
}

if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}

We create the useCounter hook with the useState and useCallback hooks.

The useState hook lets us create and set a state.

We have the value state and we can set it with the setValue function.

The increment function is created from the useCallback hook.

It takes a callback that lets us create a function to let us set states and commit side effects.

We used the callback to call setValue to set the value of value .

Then in the App component, we use the useCounter hook, which returns the value state and increment function to let us increase value by 1.

We render a button to call increment when we click it.

And we display the latest value of value .

Each instance of a hook is different from each other.

So using them in different places wouldn’t affect its state.

useState

The useState hook lets us create and set a state.

The state change will cause the component to be re-rendered.

Therefore, we can see the latest value of the state.

For example, we can write:

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

function App() {
  const [count, setCount] = useState(0);
  const increment = () => setCount(count + 1);
  const decrement = () => setCount((currentCount) => currentCount - 1);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </div>
  );
}

if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}

We create the increment function which calls the setCount function to update the state.

Also, we can pass in a callback to return the latest value of the state derived from the previous value of the state.

currentCount has the current value of the count state.

So when we click Increment, we see the count increment by 1.

And when we click Decrement, we see count decrease by 1.

useReducer

The useReducer hook takes a function that looks like a Redux reducer.

We can use it to update more complex states.

For example, we can write:

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

const initialState = 0;
const reducer = (state, action) => {
  switch (action) {
    case "increment":
      return state + 1;
    case "decrement":
      return state - 1;
    case "reset":
      return 0;
    default:
      throw new Error("Unexpected action");
  }
};

function App() {
  const [count, dispatch] = useReducer(reducer, initialState);
  return (
    <div>
      <p>{count}</p>
      <button onClick={() => dispatch("increment")}>increment</button>
      <button onClick={() => dispatch("decrement")}>decrement</button>
      <button onClick={() => dispatch("reset")}>reset</button>
    </div>
  );
}

if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}

We create the reducer function, which takes the state and action parameters.

state has the state.

action has the action name we pass into the dispatch function.

In App , we use the useReducer hook by passing in the reducer function and the initialState , which has the initial value of count .

Then we call the dispatch function to update the count state.

Conclusion

We can use various hooks with the Preact hooks package.

Also, we can compose hooks to create other hooks.

Categories
Preact

Preact — Class Components and Fragments

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.

Class Components

We can add class components as we do with React.

For example, we can write:

import { Component, render } from "preact";

class Clock extends Component {
  constructor() {
    super();
    this.state = { time: Date.now() };
  }

  componentDidMount() {
    this.timer = setInterval(() => {
      this.setState({ time: Date.now() });
    }, 1000);
  }

  componentWillUnmount() {
    clearInterval(this.timer);
  }

  render() {
    const time = new Date(this.state.time).toLocaleTimeString();
    return <span>{time}</span>;
  }
}
if (typeof window !== "undefined") {
  render(<Clock />, document.getElementById("root"));
}

We create the Clock component by creating a class that extends the Component class.

Then in the constructor , we create the time state and set it to Date.now() as the initial value.

The componentDidMount hook lets us initialize the data.

In the method, we call setInterval to create the timer and in the callback, we call setState to set the state.

componentWillUnmount is called when we unmount the component, so we call clearInterval to clear the timer when the component unmounts.

In the render method, we render the current time.

Preact methods include lifecycle methods that are included in React class components.

They include:

  • componentDidMount() — after the component gets mounted to the DOM
  • componentWillUnmount() — prior to removal from the DOM
  • getDerivedStateFromProps(nextProps) — just before shouldComponentUpdate. Use with care.
  • shouldComponentUpdate(nextProps, nextState) — before render(). Return false to skip render
  • getSnapshotBeforeUpdate(prevProps, prevState) — called just before render(). The return value is passed to componentDidUpdate.
  • componentDidUpdate(prevProps, prevState, snapshot) — after render()

Fragments

We can use the Fragment component to render multiple components without a root element.

For example, we can write:

import { Fragment, render } from "preact";

function TodoItems() {
  return (
    <Fragment>
      <li>foo</li>
      <li>bar</li>
      <li>baz</li>
    </Fragment>
  );
}

const App = (
  <ul>
    <TodoItems />
    <li>qux</li>
  </ul>
);

if (typeof window !== "undefined") {
  render(App, document.getElementById("root"));
}

We have the TodoItems component, which renders a Fragment .

The resulting HTML only has the li elements.

In App , we combine TodoItems with li and render them together.

We can use <> and </> in place of <Fragment> and </Fragment> :

import { Fragment, render } from "preact";

function TodoItems() {
  return (
    <>
      <li>foo</li>
      <li>bar</li>
      <li>baz</li>
    </>
  );
}

const App = (
  <ul>
    <TodoItems />
    <li>qux</li>
  </ul>
);

if (typeof window !== "undefined") {
  render(App, document.getElementById("root"));
}

We can also return an array of components:

import { Fragment, render } from "preact";

function TodoItems() {
  return [<li>foo</li>, <li>bar</li>, <li>baz</li>];
}

const App = (
  <ul>
    <TodoItems />
    <li>qux</li>
  </ul>
);

if (typeof window !== "undefined") {
  render(App, document.getElementById("root"));
}

This is the same as what we have before.

If we use Fragment s in a loop, then we have to add the key prop and set it to a unique value so that the items can be distinguished:

import { Fragment, render } from "preact";

const items = [
  {
    id: 1,
    term: "apple",
    description: "red fruit"
  },
  {
    id: 2,
    term: "banana",
    description: "yellow fruit"
  }
];

function Glossary({ items }) {
  return (
    <dl>
      {items.map((item) => (
        <Fragment key={item.id}>
          <dt>{item.term}</dt>
          <dd>{item.description}</dd>
        </Fragment>
      ))}
    </dl>
  );
}

const App = (
  <div>
    <Glossary items={items} />
  </div>
);

if (typeof window !== "undefined") {
  render(App, document.getElementById("root"));
}

Conclusion

We can create class components and fragments as we do with React.

Categories
Preact

Preact — Preact X Features

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.

Hooks

Just like React, Preact has hooks, and they work the same way.

For example, we can write:

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

export default function App() {
  const [value, setValue] = useState(0);
  const increment = useCallback(() => setValue(value + 1), [value]);

  return (
    <div>
      <p>count: {value}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
}

if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}

We call the useState hook to create the value state.

And we can set that with the setValue function.

And we create the function to increment the value state with the useCallback hook.

We pass in the function we want to call inside it to cache it until value changes.

And finally, we render the count and the increment button.

When we click it, we see the count increase.

createContext

The React Context API is also adopted to Preact.

The Context API lets us share data between different components.

To us it, we write:

import { createContext, render, Fragment } from "preact";

const Theme = createContext("light");

function ThemedButton() {
  return (
    <Theme.Consumer>
      {(theme) => <div>Active theme: {theme}</div>}
    </Theme.Consumer>
  );
}

function SomeComponent({ children }) {
  return <>{children}</>;
}

export default function App() {
  return (
    <div>
      <Theme.Provider value="dark">
        <SomeComponent>
          <ThemedButton />
        </SomeComponent>
      </Theme.Provider>
    </div>
  );
}

if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}

We called the createContext function with the value 'light' .

In the ThemeButton component, we render the ThemeConsumer component so we can get the theme data in the function.

In SomeComponent , we render the child elements.

And in App , we add the Theme.Provider component so that we can set the value in it.

Then anything inside the Theme.Provider component will get the value.

CSS Custom Properties

We can add CSS custom properties in our Preact components.

For example, we can write:

import { render } from "preact";

export default function App() {
  return (
    <div style={{ "--theme-color": "lightblue" }}>
      <div style={{ backgroundColor: "var(--theme-color)" }}>hello world</div>
    </div>
  );
}

if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}

We defined the --theme-color CSS variable.

Then we used it in the inner div to set the background color of it.

Components

Like React, Preact has many components.

We can use functional components as we do with React.

For example, we can write:

import { render } from "preact";

function MyComponent(props) {
  return <div>My name is {props.name}.</div>;
}

export default function App() {
  return <MyComponent name="Jane" />;
}

if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}

We create the MyComponent component and used it in App .

Conclusion

Preact X comes with many features that are available with React.