GitHub - matthewp/haunted: React's Hooks API implemented for web compone...
source link: https://github.com/matthewp/haunted
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
readme.md
Haunted ??
React's Hook API but for standard web components and lit-html.
<!doctype html> <my-counter></my-counter> <script type="module"> import { html } from 'https://unpkg.com/lit-html/lit-html.js'; import { component, useState } from 'https://unpkg.com/@matthewp/haunted/haunted.js'; function Counter() { const [count, setCount] = useState(0); return html` <div id="count">${count}</div> <button type="button" @click=${() => setCount(count + 1)}>Increment</button> `; } customElements.define('my-counter', component(Counter)); </script>
Install
For now it is available as the @matthewp/haunted
package. In the future I hope to get the non-scoped name.
npm install @matthewp/haunted
API
Haunted supports the same API as React Hooks. My hope is that by doing so you can reuse hooks available on npm simply by aliasing package names in your bundler's config.
Currently Haunted supports the following hooks:
useState
Create a tuple of state and a function to change that state.
const [count, setCount] = useState(0);
useEffect
Useful for side-effects that run after the render has been commited.
<!doctype html> <my-counter></my-counter> <script type="module"> import { html } from 'https://unpkg.com/lit-html/lit-html.js'; import { component, useState, useEffect } from 'https://unpkg.com/@matthewp/haunted/haunted.js'; function Counter() { const [count, setCount] = useState(0); useEffect(() => { document.title = `Clicked ${count} times`; }); return html` <div id="count">${count}</div> <button type="button" @click=${() => setCount(count + 1)}>Increment</button> `; } customElements.define('my-counter', component(Counter)); </script>
useReducer
Create state that updates after being ran through a reducer function.
<!doctype html> <my-counter></my-counter> <script type="module"> import { html } from 'https://unpkg.com/lit-html/lit-html.js'; import { component, useReducer } from 'https://unpkg.com/@matthewp/haunted/haunted.js'; const initialState = {count: 0}; function reducer(state, action) { switch (action.type) { case 'reset': return initialState; case 'increment': return {count: state.count + 1}; case 'decrement': return {count: state.count - 1}; } } function Counter() { const [state, dispatch] = useReducer(reducer, initialState); return html` Count: ${state.count} <button @click=${() => dispatch({type: 'reset'})}> Reset </button> <button @click=${() => dispatch({type: 'increment'})}>+</button> <button @click=${() => dispatch({type: 'decrement'})}>-</button> `; } customElements.define('my-counter', component(Counter)); </script>
useMemo
Create a memoized state value. Only reruns the function when dependent values have changed.
<!doctype html> <my-app></my-app> <script type="module"> import { html } from 'https://unpkg.com/lit-html/lit-html.js'; import { component, useMemo, useState } from 'https://unpkg.com/@matthewp/haunted/haunted.js'; function fibonacci(num) { if (num <= 1) return 1; return fibonacci(num - 1) + fibonacci(num - 2); } function App() { const [value, setVal] = useState(12); const fib = useMemo(() => fibonacci(value), [value]); return html` <h1>Fibonacci</h1> <input type="text" @change=${ev => setVal(Number(ev.target.value))} value="${value}"> <div>Fibonacci <strong>${fib}</strong></div> `; } customElements.define('my-app', component(App)); </script>
License
BSD-2-Clause
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK