Hooks

Hooks are functions that let you "hook into" PawaJS features from your components. They are essential for managing state, side effects, and interacting with the DOM.

useInsert

The useInsert hook is fundamental for making variables and functions from your component's scope available to its template. Without it, you cannot use variables in directives or interpolation.

javascript
                
import { html, useInsert } from "pawajs";

export const MyComponent = () => {
    const message = "Hello from a variable!";
    const handleClick = () => alert('Clicked!');

    // Expose to the template
    useInsert({ message, handleClick });

    return html`
        <p>@{message}</p>
        <button on-click="handleClick()">Click me</button>
    `;
};
             
            

runEffect

runEffect is PawaJS's versatile hook for managing side effects and lifecycle events. Its behavior changes based on the second argument (dependencies).

Reactive Effect (Array)

Pass an array of reactive variables. The effect runs when they change. The return function is the cleanup (unmount) handler.

javascript
                
runEffect(() => {
    console.log(`The count is now: ${count.value}`);
    return () => console.log('Cleanup/Unmount');
}, [count]); // Dependency array
                 
            

Mount Hook (null)

Pass null to run the effect only once when the component mounts. The return function runs on unmount.

javascript
                
runEffect(() => {
    console.log('Mounted');
    return () => console.log('Unmounted');
}, null);
                 
            

Before Mount (Number)

Pass any number to run the effect before the component mounts.

javascript
                
runEffect(() => console.log('Before Mount'), 1);
                 
            

Scoped/Read-Only Effect (Object)

Pass an object (like a ref or {component: true}) to create a read-only effect tied to that scope. Unlike the others, this is passed directly to the internal createEffect.

javascript
                
const divRef = useRef();
// ...
runEffect(() => {
    // Read-only effect tied to element
}, divRef.value);
             
            

useRef

useRef provides a way to get a direct reference to a DOM element. This is useful for interacting with elements imperatively, like focusing an input.

javascript
                
import { useRef, useInsert, html } from "pawajs";

const inputRef = useRef();
useInsert({ inputRef });

const focusInput = () => {
    inputRef.value.focus();
};

return html`
    <input ref="inputRef">
    <button on-click="focusInput">Focus Input</button>
`;
             
            

useValidateComponent

This hook allows you to define prop types and default values for your components, providing validation and ensuring robustness.

javascript
                
import { useValidateComponent, html } from "pawajs";

const Card = ({ title, content }) => { /* ... */ };

useValidateComponent(Card, {
    title: { type: String, required: true },
    content: { type: String, default: 'No content provided.' }
});
             
            

useContext & setContext

setContext creates a context provider mechanism, and useContext allows you to subscribe to it.

javascript
                
import { useContext, setContext, html, useInsert } from "pawajs";

// Define context globally
const ThemeContext = setContext();

const App = () => {
    // Set value for descendants
    ThemeContext.setValue({ mode: 'dark' });
    return html`<theme-button></theme-button>`;
};

const ThemeButton = () => {
    const theme = useContext(ThemeContext);
    useInsert({ theme });
    return html`<button>Current theme: @{theme.mode}</button>`;
};
             
            

useAsync

useAsync helps manage asynchronous operations within a component and provides a way to show a ui loading while the async component is waiting onSuspence

javascript
                
import { useAsync, html, $state, useInsert } from "pawajs";

const DataComponent = () => {
    const { $async, onSuspence } = useAsync();
    onSuspence(html`<loading></loading> `)
    const res = await fetch('/api/data'),then(res => res.json());
    const data = $async(()=>$state(res));
    
    $async(()=>useInsert({ data, loadData }));
    // ...
};
             
            

useServer

useServer facilitates data transfer from server-side rendering to the client. It provides setServerData to store data during SSR and getServerData to retrieve it during hydration.

On server streaming pawajs (pawa-ssr) uses useServer and useAync hook (onSuspense) to mark suspense boundaries where pawa-ssr resovles it later and update the page with the resovle asynchronous component output.

javascript
                
import { useServer, html, useInsert } from "pawajs";
import { isServer } from "pawajs/server";

const ServerDataComponent = () => {
    const { setServerData, getServerData } = useServer();
    let data = { message: "" };

    if (isServer()) {
        data = { message: "Hello from Server!" };
        setServerData(data);
    } else {
        data = getServerData() || { message: "Hydrating..." };
    }
    
    useInsert({ data });
    return html`<div>Server says: @{data.message}</div>`;
};
             
            

isResume

isResume is a helper that returns true if the current component is being hydrated (resumed) from server-rendered HTML. This is useful for distinguishing between a hydration pass and a fresh client-side render.

javascript
                
import { isResume, html } from "pawajs";

const Component = () => {
    const status = isResume() ? 'Hydrating' : 'Rendering';
    useInsert({status});
    return html`<div>@{status}</div>`;
};