Skip to main content
Functional components are the simplest way to create components in GlyphUI. They are JavaScript functions that take props as an argument and return a virtual DOM tree.

Basic Syntax

A functional component is just a function that returns a virtual DOM node created with the h() function:
import { h } from "glyphui";

const Greeting = (props) => {
  return h("h1", {}, [`Hello, ${props.name}!`]);
};

Using Functional Components

To use a functional component, wrap it with createComponent():
import { createComponent } from "glyphui";

const app = createComponent(Greeting, { name: "Alice" });

Props

Props are passed as the first argument to functional components. They contain data and functions from the parent component.
const UserCard = (props) => {
  return h("div", { class: "card" }, [
    h("h2", {}, [props.name]),
    h("p", {}, [props.email]),
    h("button", { 
      on: { click: props.onEdit } 
    }, ["Edit"])
  ]);
};

Children Prop

Children passed to a component are available under props.children:
const Container = (props) => {
  return h("div", { class: "container" }, [
    h("header", {}, ["Header"]),
    ...props.children,  // Spread children into the DOM
    h("footer", {}, ["Footer"])
  ]);
};

State Management with Hooks

Functional components can manage state using the useState hook:
import { h, useState } from "glyphui";

const Counter = (props) => {
  const [count, setCount] = useState(0);
  
  return h("div", {}, [
    h("h2", {}, ["useState Demo"]),
    h("p", {}, [`Current count: ${count}`]),
    h("button", {
      onclick: () => setCount(count + 1)
    }, ["Increment"]),
    h("button", {
      onclick: () => setCount(count - 1)
    }, ["Decrement"]),
    h("button", {
      onclick: () => setCount(0)
    }, ["Reset"])
  ]);
};
The useState hook returns an array with the current state value and a setter function.

Side Effects with useEffect

Use useEffect to handle side effects like timers, subscriptions, or data fetching:
import { h, useState, useEffect } from "glyphui";

const Timer = (props) => {
  const [time, setTime] = useState(0);
  const [isRunning, setIsRunning] = useState(false);
  
  useEffect(() => {
    let intervalId = null;
    
    if (isRunning) {
      intervalId = setInterval(() => {
        setTime((prevTime) => prevTime + 1);
      }, 1000);
    }
    
    // Cleanup function runs when effect is cleaned up
    return () => {
      if (intervalId) {
        clearInterval(intervalId);
      }
    };
  }, [isRunning]); // Re-run when isRunning changes
  
  return h("div", {}, [
    h("div", { class: "timer" }, [time.toString()]),
    h("button", {
      onclick: () => setIsRunning(!isRunning)
    }, [isRunning ? "Pause" : "Start"])
  ]);
};
The second argument to useEffect is a dependency array. The effect only re-runs when these dependencies change.

Other Hooks

useRef

Store mutable values that persist across renders without causing re-renders:
import { h, useRef, useEffect } from "glyphui";

const AutoFocusInput = (props) => {
  const inputRef = useRef(null);
  
  useEffect(() => {
    if (inputRef.current) {
      inputRef.current.focus();
    }
  }, []);
  
  return h("input", {
    type: "text",
    ref: (el) => (inputRef.current = el)
  }, []);
};

useMemo

Memoize expensive calculations:
import { h, useState, useMemo } from "glyphui";

const FibonacciCalculator = (props) => {
  const [number, setNumber] = useState(20);
  
  const fibonacci = useMemo(() => {
    console.log(`Calculating Fibonacci(${number})...`);
    const fib = (n) => {
      if (n <= 1) return n;
      if (n === 2) return 1;
      return fib(n - 1) + fib(n - 2);
    };
    return fib(number);
  }, [number]); // Only recalculate when number changes
  
  return h("div", {}, [
    h("p", {}, [`Fibonacci(${number}) = ${fibonacci}`])
  ]);
};

useCallback

Memoize callback functions:
import { h, useState, useCallback } from "glyphui";

const Form = (props) => {
  const [name, setName] = useState("");
  
  const handleSubmit = useCallback((e) => {
    e.preventDefault();
    console.log("Submitting:", name);
  }, [name]);
  
  return h("form", { onsubmit: handleSubmit }, [
    h("input", {
      value: name,
      oninput: (e) => setName(e.target.value)
    }, [])
  ]);
};

When to Use Functional Components

Best For

  • Simple, presentational UI
  • Components that use hooks
  • New component development
  • Functional programming style

Consider Class Components If

  • You need lifecycle methods
  • Complex state management
  • You prefer OOP style
  • Legacy codebase consistency

Class Components

Learn about class-based components

Component Composition

Compose components together

Build docs developers (and LLMs) love