Skip to content

Instantly share code, notes, and snippets.

@brandonros
Last active August 9, 2024 04:32
Show Gist options
  • Save brandonros/9ec876594b56d95bb60723d154c2e768 to your computer and use it in GitHub Desktop.
Save brandonros/9ec876594b56d95bb60723d154c2e768 to your computer and use it in GitHub Desktop.
Preact + Hyperscript Tagged Markup (HTM) example
<!DOCTYPE html>
<html>
<head>
<title>Preact HTM Example</title>
</head>
<body>
<script type="module">
// 1. imports from unpkg.com
import * as Preact from 'https://unpkg.com/[email protected]/dist/preact.module.js'
import htm from 'https://unpkg.com/[email protected]/dist/htm.module.js'
// 2. make htm import work with Preact import
const html = htm.bind(Preact.createElement)
// 3. define Header component
class Header extends Preact.Component {
render() {
const { name } = this.props
return html`<h1>${name} List</h1>`
}
}
// 4. define Footer component
class Footer extends Preact.Component {
render() {
const { children } = this.props
return html`<footer>${children}</footer>`
}
}
// 5. define App component
class App extends Preact.Component {
constructor() {
super()
this.state = {
todos: []
}
}
addTodo() {
const { todos } = this.state
this.setState({
todos: todos.concat(`Item ${todos.length}`)
})
}
render() {
const { page } = this.props
const { todos } = this.state
return html`
<div class="app">
<${Header} name="ToDo's (${page})"></Header>
<ul>
${todos.map(todo => html`
<li key="${todo}">${todo}</li>
`)}
</ul>
<button onClick=${() => this.addTodo()}>Add Todo</button>
<${Footer}>footer content here</Footer>
</div>
`
}
}
// 6. append rendered App component to node document.body
Preact.render(html`<${App} page="All"></App>`, document.body)
</script>
</body>
</html>
@brandonros
Copy link
Author

brandonros commented Jul 31, 2020

JavaScript syntax used

APIs used

HTML elements

HTML page with a <script> tag to load JavaScript that uses ES6 (ECMAScript 6) import to load 2 modules:

  1. Preact - https://github.com/preactjs/preact
  2. HTM - https://github.com/developit/htm

Then, defines 3 components:

  1. Header - takes in props.name, puts it as a child in an HTML <h1> element
  2. Footer - takes in props.children, puts it as child elements in a HTML <footer> element
  3. App - calls both Header + Footer components as well as div/ul/li/button. Draws a list of todo rows based on state.todos array. Binds the onClick event of button to a function that will change the state (add a todo to the array in state), which will cause the ul/li list to draw a new element.

Then, binds the new App component as an html element to document.body. This will make the render() functions we defined be called with all of our components following all of the logic (bind onclick events, change what is displayed on click, etc.)

Example:

Initial load:

image

After 3 clicks of the button:

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment