0.6.8 • Published 2 months ago

light-jsx v0.6.8

Weekly downloads
-
License
MIT
Repository
github
Last release
2 months ago

Light JSX · GitHub license · npm version · bundle size · typescript used

Light JSX is a simple JavaScript library for creating reactive websites. It doesn't use any behind scene magic, like Virtual DOM or compilation, to render your apps, all JSX translated directly to nodes and updates them when state of your app changes.

  • No compilation step. Your app doesn't need any additional compilation steps. Typescript will do everything needed.
  • Light. Package size is 2 times less than other popular JSX libraries.
  • Native. Every JSX turns into DOM nodes, that makes debugging less painfull.
  • Simple. It's very easy to understand, especially if you used JSX libraries before.
  • Fine grained reactivity. DOM changes only when and where needed.

Instalation

First, install light-jsx.

npm i light-jsx

Then add this lines to your tsconfig.json.

    "jsx": "react",
    "jsxFactory": "LightJSX.DOMcreateElement",
    "jsxFragmentFactory": "LightJSX.Fragment"

And you are ready to start!

Examples

Hello world example

import { LightJSX } from "light-jsx"

// equal to <div>Hello world!</div>, surprising, isn't it?
let hello = <div>Hello world!</div>

LightJSX.render(document.body, hello)

Counter example

import { LightJSX, createSignal } from "light-jsx"

// creating state
// val = Getter<number>
// setVal = Setter<number>
const [val, setVal] = createSignal(0)

// changing state on click and displaying it
let counter = <button onclick={() => setVal((c) => c + 1)}>Count: {val}</button>

LightJSX.render(document.body, counter)

Computed example

import { LightJSX, createComputed, createSignal } from "light-jsx"

// creating state
// val = Getter<number>
// setVal = Setter<number>
const [val, setVal] = createSignal(0)

// creating computed
const double = createComputed(() => val() * 2)

// changing state on click and displaying it
let counter = (
    <>
        <button onclick={() => setVal((c) => c + 1)}>Count: {val}</button>
        <div>double: {double}</div>
    </>
)

LightJSX.render(document.body, counter)

Effect example

In this app a() + b() will be equal to sum() in any case

import { LightJSX, createEffect, createSignal } from "light-jsx"

// states
const [a, setA] = createSignal(0)
const [b, setB] = createSignal(0)
const [sum, setSum] = createSignal(0)

// effects
// every time sum or b changes, this code will run
createEffect(() => {
    setA(sum() - b())
})

// every time sum or a changes, this code will run
createEffect(() => {
    setB(sum() - a())
})

// keep in mind, that effects will run once immediately after they setup

// rendering multiple elements using fragment
const app = (
    <>
        <button onclick={() => setA((a) => a + 1)}>{a}</button>
        <span>+</span>
        <button onclick={() => setB((b) => b + 1)}>{b}</button>
        <span>=</span>
        <button onclick={() => setSum((sum) => sum + 1)}>{sum}</button>
    </>
)

LightJSX.render(document.body, app)

Function components

import { LightJSX, createEffect, createSignal } from "light-jsx"

// function component with props type declaration
// also keep in mind, that it will be called once per component
function StrangeCalculator(props: { initialSum?: number }) {
    const [a, setA] = createSignal(0)
    const [b, setB] = createSignal(0)
    const [sum, setSum] = createSignal(props.initialSum ?? 0)

    createEffect(() => {
        setA(sum() - b())
    })

    createEffect(() => {
        setB(sum() - a())
    })

    // styles
    return (
        <div style={{ "padding": "6px" }}>
            <button onclick={() => setA((a) => a + 1)}>{a}</button>
            <span>+</span>
            <button onclick={() => setB((b) => b + 1)}>{b}</button>
            <span>=</span>
            <button onclick={() => setSum((sum) => sum + 1)}>{sum}</button>
        </div>
    )
}

// rendering multiple components won't break anything
LightJSX.render(document.body, <StrangeCalculator initialSum={10} />)
LightJSX.render(document.body, <StrangeCalculator />)
LightJSX.render(document.body, <StrangeCalculator initialSum={100} />)

How it works

As you might point out getter is function, but when passing it as JSX child we don't call it. Every function passed as JSX child is considered state dependand and will be rerendered every time signals used inside it changes.

This code will log every time val is changed, because getVal is dependand on it.

import { LightJSX, createSignal } from "light-jsx"

const [val, setVal] = createSignal(0)

const getVal = () => {
    console.log("getting value: ", val())
    return val()
}

let counter = <button onclick={() => setVal((c) => c + 1)}>Count: {getVal}</button>

LightJSX.render(document.body, counter)

Based on this you may already guessed how poor use of library would look.

Bad code examples. Don't repeat it at home.

// this won't update at all, because there are no function
// functions is the key for reactivity
let badCounter1 = <button onclick={() => setVal((c) => c + 1)}>Count: {val()}</button>

// this will update
// but instead of rendering element once, it will rerender everything every time val changes
let badCounter2 = () => <button onclick={() => setVal((c) => c + 1)}>Count: {val()}</button>

let double = () => val() * 2
// this code will compute double 8 times
// instead you can use createComputed, that will run calculations once
let overlyExaggeratedExample = (
    <div>
        {double} {double} {double} {double} {double} {double} {double} {double}
    </div>
)

Happy coding!

0.6.7

2 months ago

0.6.6

2 months ago

0.6.8

2 months ago

0.6.3

2 months ago

0.6.5

2 months ago

0.6.4

2 months ago

0.6.2

2 months ago

0.5.0

3 months ago

0.4.1

3 months ago

0.6.1

3 months ago

0.6.0

3 months ago

0.4.2

3 months ago

0.4.0

3 months ago

0.3.7

7 months ago

0.3.6

7 months ago

0.3.5

8 months ago

0.3.4

8 months ago

0.3.3

8 months ago

0.3.2

8 months ago

0.3.1

8 months ago

0.3.0

8 months ago

0.2.13

8 months ago

0.2.12

8 months ago

0.2.11

8 months ago

0.2.10

8 months ago

0.2.9

8 months ago

0.2.8

8 months ago

0.2.7

8 months ago

0.2.6

8 months ago

0.2.5

8 months ago

0.2.4

8 months ago

0.2.3

8 months ago

0.2.2

8 months ago

0.2.1

8 months ago

0.2.0

8 months ago

0.1.1

8 months ago

0.0.1

8 months ago