Categories
Preact

Preact — Shallow Rendering, Pretty Print, and External DOM Mutations

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.

Shallow Rendering

We can shallow render one level of a component only with shallow rendering.

For example, we can write:

import { shallowRender } from "preact-render-to-string";
import { h } from "preact";

const Foo = () => <div>foo</div>;
const App = (
  <div class="foo">
    <Foo />
  </div>
);

console.log(shallowRender(App));

to render the App component without rendering the Foo component.

Then when we log the returned string, we get:

'<div class="foo"><Foo></Foo></div>'

logged.

Pretty Mode

We can render the string in a more human-friendly way with the pretty option.

To use it, we write:

import { render } from "preact-render-to-string";
import { h } from "preact";

const Foo = () => <div>foo</div>;
const App = (
  <div class="foo">
    <Foo />
  </div>
);

console.log(render(App, {}, { pretty: true }));

Then we see:

<div class="foo">
 <div>foo</div>
</div>

logged.

JSX Mode

The JSX rendering mode is useful if we’re doing any kind of snapshot testing.

It renders the output as if it’s written with JSX.

For example, we can write:

import render from "preact-render-to-string/jsx";
import { h } from "preact";

const App = <div data-foo={true} />;

console.log(render(App));

Then we see:

<div data-foo={true}></div>

logged.

External DOM Mutations

We can add external DOM mutation code in our component.

To do this, we have to disable the virtual DOM rendering and diffing algorithm so that it won’t undo any external DOM manipulations in a component.

For example, we can write:

import { Component, render } from "preact";

class Example extends Component {
  shouldComponentUpdate() {
    return false;
  }

  componentDidMount() {
    let thing = document.createElement("maybe-a-custom-element");
    this.base.appendChild(thing);
  }

  componentWillUnmount() {}

  render() {
    return <div class="example" />;
  }
}

const App = () => <Example />;

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

We return false in shouldComponentUpdate to disable the virtual DOM diffing algorithm.

Then in componentDidMount , we call document.createElement to add a new element into the DOM.

Conclusion

We can shallow render and pretty print components rendered in a string.

Also, we can manipulate the DOM directly in our Preact components.

Categories
Preact

Preact — Create Web Component and Server Side Rendering

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.

Creating a Web Component

We can convert a Preact component into a web component with the preact-custom-element package.

For example, we can write:

import { render } from "preact";
import register from "preact-custom-element";

const Greeting = ({ name = "World" }) => <p>Hello, {name}!</p>;

register(Greeting, "x-greeting", ["name"]);

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

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

to import the register function to register our Preact component as a web component.

We have the Greeting component which we register as the x-greeting custom element.

The 3rd argument has the attribute that x-greeting takes, which is the name attribute.

It’ll be interpolated into the p element in Greeting like we have with a regular Preact component.

In App , we use th x-greeting web component with the name prop set.

Then we see:

Hello, Jane!

displayed.

Observed Attributes

We have to make attributes observable so that it can respond to value changes.

To make them observable, we can write:

import { Component, render } from "preact";
import register from "preact-custom-element";

class Greeting extends Component {
  static tagName = "x-greeting";
  static observedAttributes = ["name"];

  render({ name }) {
    return <p>Hello, {name}!</p>;
  }
}
register(Greeting);

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

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

We create our Greeting component.

Then we set the tagName static property to set its tag name.

And we set the observedAttributes to an array of attribute names to watch.

In App , we use the x-greeting component the same way.

If no observableAttributes are specified, then the data type of the attributes will be inferred from the keys of propTypes .

Setting the propTypes will make them observable.

For example, if we have:

import { render } from "preact";
import register from "preact-custom-element";

function FullName({ first, last }) {
  return (
    <span>
      {first} {last}
    </span>
  );
}

FullName.propTypes = {
  first: Object,
  last: Object
};

register(FullName, "full-name");
export default function App() {
  return <full-name first="Jane" last="Smith"></full-name>;
}

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

We set the first and last prop types to Object and they’ll be made observable.

Server-Side Rendering

We can render Preact components to strings.

This lets us render content on the server-side, which is useful for increasing performance.

For example, we can write:

import render from "preact-render-to-string";

const App = <div class="foo">content</div>;

console.log(render(App));

render renders the App component to a string.

Now we should see:

<div class="foo">content</div>

logged in the console log.

Conclusion

We can create web components from Preact components.

Also, we can render components to strings.

Categories
Preact

Preact — Using Web Components

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.

Web Components

We can render web components in our Preact component.

For example, we can write:

import { Component, render } from "preact";

window.customElements.define(
  "x-foo",
  class extends HTMLElement {
    constructor() {
      super();
      let tmpl = document.createElement("template");
      tmpl.innerHTML = `
        <b>I am in the shadown dom</b>
        <slot></slot>
      `;
      let shadowRoot = this.attachShadow({ mode: "open" });
      shadowRoot.appendChild(tmpl.content.cloneNode(true));
    }
  }
);

export default class App extends Component {
  render() {
    return <x-foo position={{ x: 10, y: 20 }}>foo bar</x-foo>;
  }
}
if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}

We call customElements.define to create our web component.

Then we reference it in the App component and add our content inside the slot .

We can use the x and y properties by writing:

import { Component, render } from "preact";

window.customElements.define(
  "x-foo",
  class extends HTMLElement {
    constructor() {
      super();
      let tmpl = document.createElement("template");
      tmpl.innerHTML = `
        <b>I am in the shadown dom</b>
        <slot></slot>
      `;
      let shadowRoot = this.attachShadow({ mode: "open" });
      shadowRoot.appendChild(tmpl.content.cloneNode(true));
    }

    set position({ x, y }) {
      this.style.cssText = `left:${x}px; top:${y}px; position: absolute`;
    }
  }
);

export default class App extends Component {
  render() {
    return <x-foo position={{ x: 10, y: 20 }}>foo bar</x-foo>;
  }
}
if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}

We add the position setter.

Then we set the this.style.cssText property to set the position of the x-foo component.

Therefore, the x-foo component has the position values applied to it.

We can also call methods in web component classes.

To do this, we assign a ref to the web component.

Then we can call the methods in the web component class:

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

window.customElements.define(
  "x-foo",
  class extends HTMLElement {
    constructor() {
      super();
      let tmpl = document.createElement("template");
      tmpl.innerHTML = `
        <b>I am in the shadown dom</b>
        <slot></slot>
      `;
      let shadowRoot = this.attachShadow({ mode: "open" });
      shadowRoot.appendChild(tmpl.content.cloneNode(true));
    }

    set position({ x, y }) {
      this.style.cssText = `left:${x}px; top:${y}px; position: absolute`;
    }

    doSomething() {
      console.log("did something");
    }
  }
);

export default function App() {
  const myRef = useRef(null);

  useEffect(() => {
    if (myRef.current) {
      myRef.current.doSomething();
    }
  }, []);

  return <x-foo ref={myRef} />;
}
if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}

We set the ref prop to the myRef ref object, which is created from the useRef hook.

Then in the useEffect callback, we call myRef.current.doSomething() method to call the doSomething method in the web component.

Listen to Web Component Events

We can listen to web components. For example, we can write:

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

window.customElements.define(
  "x-foo",
  class extends HTMLElement {
    constructor() {
      super();
      let tmpl = document.createElement("template");
      tmpl.innerHTML = `
        <b>I am in the shadown dom</b>
        <slot></slot>
      `;
      let shadowRoot = this.attachShadow({ mode: "open" });
      shadowRoot.appendChild(tmpl.content.cloneNode(true));
    }

    set position({ x, y }) {
      this.style.cssText = `left:${x}px; top:${y}px; position: absolute`;
    }

    connectedCallback() {
      this.shadowRoot.addEventListener("click", function (e) {
        console.log("listend to click event");
        console.log(e);
      });
    }
  }
);

export default function App() {
  return <x-foo onclick={() => console.log("click")}>foo bar</x-foo>;
}
if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}

We call addEventListener to add the click event listener to our web component.

And we set the onclick prop to assign an event listener for the click event.

So when we click on the text, we should see the console log from both event listeners called.

Conclusion

We can use web components directly in our Preact app.

Categories
Preact

Preact — Checkboxes, Radio Buttons, and Refs

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.

Checkboxes and Radio Buttons

We can add checkboxes or radio buttons and get their selected values.

For example, we can write:

import { Component, render } from "preact";

export default class App extends Component {
  toggle = (e) => {
    let checked = !this.state.checked;
    this.setState({ checked });
  };

  render(_, { checked }) {
    return (
      <label>
        <input type="checkbox" checked={checked} onClick={this.toggle} />
      </label>
    );
  }
}
if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}

We create the checked state.

Then we pass that into the checked prop.

The onClick prop is set to the toggle method.

And we call setState to set the checked state.

We can add radio buttons by writing:

import { Component, render } from "preact";

export default class App extends Component {
  constructor() {
    super();
    this.state = {
      fruit: "apple"
    };
  }

onChangeValue = (event) => {
    this.setState({ fruit: event.target.value });
  };

render(_, { fruit }) {
    return (
      <div onChange={this.onChangeValue}>
        <input
          checked={fruit === "apple"}
          type="radio"
          value="apple"
          name="fruit"
        />{" "}
        apple
        <input
          checked={fruit === "orange"}
          type="radio"
          value="orange"
          name="fruit"
        />{" "}
        orange
        <input
          checked={fruit === "grape"}
          type="radio"
          value="grape"
          name="fruit"
        />{" "}
        grape
      </div>
    );
  }
}
if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}

We add the radio buttons.

Then we watch for changes in radio button selection with the onChange callback.

In the onChangeValue method, we call setState to set the fruit state.

In the input s, we set the checked prop to set the checked state of the radio button.

We get the fruit state from the render method and check against that to set the checked state.

createRef

We call the createRef function to return a plain object with the current property.

Whenever the render method is called, Preact will assign the DOM node or component to current .

For example, we can write:

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

export default class App extends Component {
  ref = createRef();

  componentDidMount() {
    console.log(this.ref.current);
  }

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

to assign our ref to the div.

So when we log this.ref.current , we’ll see the div logged.

Callback Refs

We can also get a reference to an element by passing in a callback function.

For example, we can write:

import { Component, render } from "preact";

export default class App extends Component {
  ref = null;
  setRef = (dom) => (this.ref = dom);

  componentDidMount() {
    console.log(this.ref);
  }

  render() {
    return <div ref={this.setRef}>foo</div>;
  }
}
if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}

We have the setRef function with the dom parameter, which has the DOM node that we passed this function as the value of ref to.

Since we passed it in as the value of the ref prop in the div, the div is dom ‘s value.

We assigned it to this.ref so that we can access it.

And in the componentDidMount hook, we log the value of this.ref and we see that its value is the div.

Conclusion

We can add checkboxes and radio buttons easily with Preact.

And we can get DOM elements with refs.

Categories
Preact

Preact — Form Inputs and Dropdowns

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.

Forms

We can handle form inputs in Preact as we do with plain JavaScript and HTML.

We can create uncontrolled components, which are input components where we don’t manage the value of the input.

For example, we can write:

import { render } from "preact";

export default function App() {
  return (
    <div>
      <input onInput={(e) => console.log(e.target.value)} />;
    </div>
  );
}
if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}

to add an uncontrolled input component.

We get the input value from the e.target.value property but we don’t set the value prop with it.

To create a controlled component, we can set the value prop of it:

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

export default function App() {
  const [value, setValue] = useState();
  return (
    <div>
      <p>{value}</p>
      <input value={value} onInput={(e) => setValue(e.target.value)} />;
    </div>
  );
}
if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}

The onInput callback calls setValue to set the value state.

Then we display value and pass it into the value prop of the input.

Creating A Simple Form

We can create a simple form easily with Preact.

For instance, we can write:

import { Component, render } from "preact";

export default class App extends Component {
  state = { value: "" };

  onSubmit = (e) => {
    alert("Submitted");
    e.preventDefault();
  };

  onInput = (e) => {
    const { value } = e.target;
    this.setState({ value });
  };

  render(_, { value }) {
    return (
      <form onSubmit={this.onSubmit}>
        <input type="text" value={value} onInput={this.onInput} />
        <p>You typed this value: {value}</p>
        <button type="submit">Submit</button>
      </form>
    );
  }
}
if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}

We created a component class that has the onSubmit method that’s used as the value of the onSubmit prop.

It’ll be called when we click Submit.

The input calls onInput when we enter something.

We get the value entered with the e.target.value property.

We get the value state from the 2nd parameter of the render function.

Select Input

We can add a select input with code similar to the previous example.

For example, we can write:

import { Component, render } from "preact";

export default class App extends Component {
  state = { value: "" };

  onChange = (e) => {
    this.setState({ value: e.target.value });
  };

  onSubmit = (e) => {
    alert("Submitted " + this.state.value);
    e.preventDefault();
  };

  render(_, { value }) {
    return (
      <form onSubmit={this.onSubmit}>
        <select value={value} onChange={this.onChange}>
          <option value="A">A</option>
          <option value="B">B</option>
          <option value="C">C</option>
        </select>
        <button type="submit">Submit</button>
      </form>
    );
  }
}
if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}

to add a select element into our App component.

We listen to the change event with the onChange callback.

And we set the value prop to the value state.

When we click Submit, the onSubmit method runs.

And we see the alert displayed with the value that we selected.

Conclusion

We can add form inputs and dropdowns easily with Preact.