Skip to content

Getting Started

ssleert edited this page Mar 11, 2024 · 5 revisions

Getting Started

Before we start, install Hywer + Vite template first

git clone https://github.com/ssleert/hywer-vite-template.git ./hywer-test
cd ./hywer-test
npm i
npm run dev

Your first Hywer app: a simple Hello page

const App = () => {
  return <>
    <p>👋Hello</p>
    <ul>
      <li>🗺️World</li>
      <li>
        <a href="https://github.com/ssleert/hywer">
          Hywer🥢
        </a>
      </li>
    </ul>
  </>
}

document.getElementById("app").append(...<><App /></>)
  • The code should be self-explanatory if you are already familiar with plain js and html. This code is written using JSX which allows us to create Elements using a clear XML-like syntax.

  • Using JSX in most cases requires first translating the code into vanilla js. This is usually done with tools like babel, esbuild or webpack.

  • Unlike React and Vue, Hywer does not add a Virtual DOM layer between your JSX elements and the real DOM. Your <p> is a real HTMLParagraphElement that you can interact with using native browser API.

Second app: synced fields

import { ref } from "hywer"

const App = () => {
  const text = ref("")

  return <>
    <input value={text} onInput={e => text.val = e.target.value} />
    <input value={text} onInput={e => text.val = e.target.value} />
  </>
}

document.getElementById("app").append(...<><App /></>)
  • ref(value) provides an observer for value also usually called Reactive Values. That can be connected to DOM. And reactively update it value in DOM Node or Element attribute (as value={text} here).

  • ⚠️ While you can update Reactive Values by setting the val property, you should never mutate the underlying object of val itself. Doing so will not trigger the DOM tree update as you would expect and might result in undefined behavior due to aliasing.

  • on... attributes provides as a convenient interface for addEventListener(). After on you can write any event name in any case, but camelCase is preferred (like onClick, onInput, onBeforeToggle, onPaste etc).

Third app: stopwatch

import { ref, derive } from "hywer"

const App = () => {
  const elapsed = ref(0)
  let id = null

  const start = () => {
    id = (id == null)
      ? setInterval(() => elapsed.val += 0.01, 10)
      : null
  }

  const elapsedString = elapsed.derive(val => val.toFixed(2) + "s ")

  // you can also write like this if u want to derive from multiple values:
  //
  //   const elapsedString = derive(refs => {
  //     return refs[0].val.toFixed(2) + "s "
  //   }, [elapsed])

  return <>
    <pre style="display: inline;">
      {elapsedString}
    </pre>

    <button onClick={start}>Start</button>
    <button onClick={() => { clearInterval(id); id = null }}>
      Stop
    </button>
    <button onClick={() => elapsed.val = 0}>Reset</button>
  </>
}

document.getElementById("app").append(...<><App /></>)
  • value.derive(fn) or derive(fn, refs) can help in such cases when you want to make another reactive value that updates when it parent or parents updates.

Fourth app: Counter with console.log()

import { ref, effect } from "hywer"

const App = () => {
  const count = ref(0)
  
  count.sub = (val, oldVal) => {
    console.log(`count.val = ${val}; count.oldVal = ${oldVal}`)
  }

  // you can also write like this if u want to make effect for multiple values:
  //   effect(([count]) => {
  //     console.log(`count.val = ${count.val}; count.oldVal = ${count.oldVal}`)
  //   }, [count])

  return <>
    ❤️  {count}
    <button onClick={() => count.val++}>👍</button>
    <button onClick={() => count.val--}>👎</button>
  </>
}

document.getElementById("app").append(...<><App /></>)
  • set value.sub or effect(fn, refs) can help when you want to do a side-effect on a value change without connecting the derived value to the DOM

  • ⚠️ Do not add values.sub or effect(fn, refs) on variables from the parent scope in code that may be run more than once. This can lead to memory leaks because lambdas have different references for each creation and Set of subscribers will eventually overflow because gc can't figure out which subscribers to clear.

Conclusion

This was a short introductory course on Hywer.

  • I highly recommend figuring out how Hywer works under the hood, the code is quite documented and easy to understand. Code Link

  • API documentation.

  • Sample applications.

    • 🚧 Work in progress.