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.

Categories
Preact

Getting Started with Front End Development with Preact

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.

Getting Started

We can import the Preact module and call render to render the content we want.

For example, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>app</title>
  </head>
  <body>
    <script type="module">
      import { h, Component, render } from "https://unpkg.com/preact?module";
      const app = h("h1", null, "Hello World");
      render(app, document.body);
    </script>
  </body>
</html>

We call the h method from the preact module to render an element.

The first argument of h is the tag name.

The 2nd argument is the element attributes.

The 3rd argument is the content.

Then we call render with the app and document.body to render app in the body .

Alternatives to JSX

We can also use template strings to render elements.

To do this, we write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>app</title>
  </head>
  <body>
    <script type="module">
      import { h, Component, render } from "https://unpkg.com/preact?module";
      import htm from "https://unpkg.com/htm?module";
      const html = htm.bind(h);
      function App(props) {
        return html`<h1>Hello ${props.name}!</h1>`;
      }

      render(html`<${App} name="james" />`, document.body);
    </script>
  </body>
</html>

We import the html function and bind the this value in html to the h function.

Then we can use that to render our content with a template string.

We pass in the props to App just like we do with React.

Then we call render with the html tag again with the template string for App .

Preact CLI

We can use the Preact CLI to create a production-ready Preact project.

To install it globally, we run:

npm install -g preact-cli

Then we can make a production build with:

npm run build

Preact X

Preact X comes with many new features.

One feature includes fragments. It’s a container component that lets us add multiple components in one root container.

For example, we can write:

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

export default class App extends Component {
  render(props, { results = [] }) {
    return (
      <>
        <div>foo</div>
        <div>bar</div>
      </>
    );
  }
}

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

We import the Fragment component, then we can use the <> and </> symbols to add our fragment.

This works like how it is in React.

componentDidCatch

We can catch errors with the componentDidCatch method.

For example, we can write:

import { Component, render } from "preact";

export default class App extends Component {
  state = { errored: false };

  componentDidCatch(error) {
    this.setState({ errored: true });
  }

  render(props, state) {
    if (state.errored) {
      return <p>error</p>;
    }
    return props.children;
  }
}

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

to catch any errors that are raised in the render or other lifecycle methods.

Conclusion

We can create simple apps with Preact easily.

Categories
Gatsby.js

Gatsby.js — Scroll Position, Dynamic Navigation, and Link States

Gatsby is a static web site framework that’s based on React.

We can use it to create static websites from external data sources and more.

In this article, we’ll look at how to create a site with Gatsby.

Scroll Restoration

We can restore the scrolling position after refresh with Gatsby.

For example, we can write:

import React from "react"
import { useScrollRestoration } from "gatsby"

const IndexPage = () => {
  const ulScrollRestoration = useScrollRestoration(`page-component-ul-list`)

return (
    <ul style={{ height: 200, overflow: `auto` }} {...ulScrollRestoration}>
      {Array(100).fill().map((_, i) => i).map(n => (
        <li key={n}>{n}</li>
      ))}
    </ul>
  )
}

export default IndexPage

We use the useScrollRestoration hook with the 'page-component-ul-list' argument to let us create an object to restore the scrolling position.

Then we spread that object’s properties as props of the ul to let us restore the scrolling position.

Location Data from Props

We can get location data from props.

To do this, we write:

gatsby-config.js

module.exports = {
  siteMetadata: {
    siteURL: 'http://example.com'
  }
}

src/pages/foo.js

import React from "react"
import { graphql } from "gatsby"

const FooPage = ({ location, data }) => {
  const canonicalUrl = data.site.siteMetadata.siteURL + location.pathname
  return <div>The URL of this page is {canonicalUrl}</div>
}

export const query = graphql`
  query PageQuery {
    site {
      siteMetadata {
        siteURL
      }
    }
  }
`

export default FooPage

We get the siteMetadata.siteURL from the gatsby-config.js via the GraphQL query.

Then we get the location prop’s pathname property to get the path to the FooPage .

So we should see:

The URL of this page is http://example.com/foo

displayed when we go to http://localhost:8000/foo.

Providing State to a Link Component

We can provide state to a Link component.

For example, we write:

src/pages/index.js

import { Link } from "gatsby"
import React from "react"

const IndexPage = () => {
  return <>
    <div>hello world</div>
    <Link
      to={'/foo'}
      state={{ id: 1 }}
    >
      go to foo
    </Link>
  </>
}

export default IndexPage

src/pages/foo.js

import React from "react"

const FooPage = ({ location }) => {
  const { state = {} } = location
  const { id } = state
  return <div>id: {id}</div>
}

export default FooPage

We pass an object into the state prop.

Then in FooPage , we get the location prop’s state.id property to get the id property that we passed into the state prop.

Dynamic Navigation

We can add navigation dynamically with Gatsby.

To do this, we write:

module.exports = {
  siteMetadata: {
    title: 'Gatsby Starter',
    menuLinks: [
      {
        name: 'home',
        link: '/'
      },
      {
        name: 'foo',
        link: '/foo'
      }
    ]
  },
  plugins: []
}

src/components/layout.js

import React from "react"
const { StaticQuery, Link } = require("gatsby");

const Header = ({ siteTitle, menuLinks }) => (
  <header
    style={{
      background: "green",
      marginBottom: "1.45rem",
    }}
  >
    <div>
      <h1 style={{ margin: 5, flex: 1 }}>
        <Link
          to="/"
          style={{
            color: "white",
            textDecoration: "none",
          }}
        >
          {siteTitle}
        </Link>
      </h1>
      <div>
        <nav>
          <ul style={{ display: "flex", flex: 1 }}>
            {menuLinks.map(link => (
              <li
                key={link.name}
                style={{
                  listStyleType: `none`,
                  padding: `1rem`,
                }}
              >
                <Link style={{ color: `white` }} to={link.link}>
                  {link.name}
                </Link>
              </li>
            ))}
          </ul>
        </nav>
      </div>
    </div>
  </header>
)

const Layout = ({ children }) => (
  <StaticQuery
    query={graphql`
        query SiteTitleQuery {
          site {
            siteMetadata {
              title
              menuLinks {
                name
                link
              }
            }
          }
        }
      `}
    render={data => (
      <>
        <Header menuLinks={data.site.siteMetadata.menuLinks} siteTitle={data.site.siteMetadata.title} />
        <div
          style={{
            margin: '0 auto',
            maxWidth: 960,
            padding: '0px 1.0875rem 1.45rem',
            paddingTop: 0,
          }}
        >
          {children}
        </div>
      </>
    )}
  />
)

export default Layout;

src/pages/index.js

import { Link } from "gatsby"
import React from "react"
import Layout from "../components/layout"

const IndexPage = () => {
  return <>
    <Layout>
      <div>hello world</div>
    </Layout>
  </>
}

export default IndexPage

src/pages/foo.js

import React from "react"
import Layout from "../components/layout"

const FooPage = () => {
  return <div>
    <Layout>
      <div>foo</div>
    </Layout>
  </div>
}

export default FooPage

We add the menuLinks array into gatsby-config.js to add the data for the links.

Then in layout.js , we get the link data and then render them.

The Header component takes the siteTitle and menuLinks props and render the data into HTML.

siteTitle has the title of the site.

menuLinks is an array of data that we have from gatsby-config.js ‘s menuLinks property.

Then in the Layout component, we add the StaticQuery component to make the query for the menu link data.

The render prop has the result of the query in the data parameter.

And we render the links and title with the Header component.

The div has the child components that we have inside the Layout component tags.

Conclusion

We can restore the scroll position after refresh with Gatsby.

Also, we can get location data from props.

And we can create links dynamically from the site’s metadata.