Function Component

Markup does not ship with a dedicated component API. Components are simply functions that return a HTMLTemplate instance.

javascript
1const MyButton = () => {2    return html` <button type="button">click me</button> `3}

It is totally up to you what these functions can do or look like. From the example above, you can simply render your component using the render method.

javascript
1MyButton().render(document.body)

Inputs (Props)

Since its functions, you can take arguments and inject them directly into the template with proper defaults handling.

javascript
1const Button = ({ content = '', disabled = false, type = 'button' }) => {2    return html` <button type="${type}" disabled="${disabled}">3        ${content}4    </button>`5}

Templates can take raw values or functions that returns some value which can be a state or simply a dynamic value, in that case, you can have your input type definition use the StateGetter type.

typescript
1enum MyButtonType {2    Button = 'button',3    Reset = 'reset',4    Submit = 'submit',5}6 7interface MyButtonProps {8    content: unknown9    disabled: boolean | StateGetter<boolean>10    type: MyButtonType | StateGetter<MyButtonType>11}

The StateGetter allows you to communicate that your component takes function values as input which makes it easier to work with states.

Lifecycles

You can take advantage of both effect and html lifecycles to react to things like component mounted, unmounted, and updates to do everything you need.

javascript
1const ChatMessages = () => {2    const [messages, updateMessages] = state([])3 4    onUpdate(() => {5        // todo: scroll to the bottom to show latest msg6    })7 8    const onMount = () => {9        const controller = new AbortController();10        const signal = controller.signal;11 12        fetch('...', { signal })13            .then((res) => {14                if(!res.ok) throw new Error(res.statusText)15 16                return res.json()17            })18            .then((res) => updateMessages(res.messages))19            .catch(console.error);20 21        // return a function to be called on unmount22        // where you can perform any clean ups23        return () => {24            controller.abort();25        }26    }27 28    return html`29        <ul>30            ${repeat(messages, msg => html`<li>${msg}</li>31        </ul>32    `)}33        .onMount(onMount)34        .onUpdate(onUpdate)35}

Markup template has powerful lifecycles and because a function is called once and with power of reactivity, you can encapsulate everything inside the function leaving everything to Markup to manage.

edit this doc