<div id="app"></div> <script src="https://unpkg.com/vue"></script> <script type="module"> import { withHooks, useState, useEffect } from './index.js' // a custom hook that fetches from an API endpoint function useAPI(endpoint) { const [res, setRes] = useState({ status: 'pending', data: null, error: null }) useEffect(() => { let aborted = false setRes({ status: 'pending', data: null, error: null }) fetch(endpoint) .then(res => res.json()) .then(data => { if (aborted) { return } setRes({ status: 'success', data, error: null }) }).catch(error => { if (aborted) { return } setRes({ status: 'error', data: null, error }) }) return () => { aborted = true } }, [endpoint]) return res } // a custom hook that sync with window width function useWindowWidth() { const [width, setWidth] = useState(window.innerWidth) const handleResize = () => { setWidth(window.innerWidth) }; useEffect(() => { window.addEventListener("resize", handleResize) return () => { window.removeEventListener("resize", handleResize) } }, []) return width } const Foo = withHooks(h => { // state const [count, setCount] = useState(0) // effect useEffect(() => { document.title = "count is " + count }) // custom hook const width = useWindowWidth() const { status, data, error } = useAPI(`https://jsonplaceholder.typicode.com/todos/${count + 1}`) let result if (status === 'pending') { result = h('div', 'loading...') } else if (status === 'success') { result = h('pre', JSON.stringify(data)) } else { result = h('pre', { style: { color: 'red' }}, error.toString()) } return h("div", [ result, h("span", `count is: ${count}`), h( "button", { on: { click: () => setCount(count + 1) } }, "+" ), h("div", `window width is: ${width}`) ]) }) // just so you know this is Vue... new Vue({ el: "#app", render(h) { return h("div", [h(Foo), h(Foo)]) } }) </script>