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 DOMcomponentWillUnmount()
— prior to removal from the DOMgetDerivedStateFromProps(nextProps)
— just beforeshouldComponentUpdate
. Use with care.shouldComponentUpdate(nextProps, nextState)
— beforerender()
. Returnfalse
to skip rendergetSnapshotBeforeUpdate(prevProps, prevState)
— called just beforerender()
. The return value is passed tocomponentDidUpdate
.componentDidUpdate(prevProps, prevState, snapshot)
— afterrender()
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.