Preact - Component Types

Quick overview of Preact´s v10 most common Component Types

Calendar Regular Icon 2025-11-05 - Snippet - Ardian Shala

Functional Component

A Functional Component is the simplest form of a Preact component. Sometimes called “dumb” component - as it doesn´t have a logic part. It takes optional props and returns JSX.

// without any Props
const FunctionalComponent = () => <div>Function Component</div>;

// with Props
const FunctionalComponent = props => <div>{props.title}</div>;

State Component with Hook

A Stateful Component uses hooks like useState and useEffect to manage local state and side effects in a functional way.

const HookComponent = ({ initialCount = 0 }) => {
	const [count, setCount] = useState(initialCount);

	useEffect(() => {
		console.log(`Count updated: ${count}`);
	}, [count]);

	return (
		<div>
			<p>Current count: {count}</p>
			<button onClick={() => setCount(count + 1)}>+1</button>
		</div>
	);
};

Signal Component

A Signal Component is a modern reactive approach to manage state and updates. Instead of relying on re-renders triggered by state changes, it automatically updates only the parts of the UI that depend on a specific signal, resulting in highly efficient and predictable rendering behavior.

import { signal, computed, effect } from '@preact/signals';

export const App = () => {
	const name = signal('John');
	const surname = signal('Doe');
	const fullName = computed(() => name.value + ' ' + surname.value);
	const count = signal(0);

	effect(() => console.log(`count changed to: ${count}`));

	return (
		<>
			<h3>Hello, {fullName}</h3>
			<input
				class="form-control"
				value={name}
				onInput={event => (name.value = event.currentTarget.value)}
			/>
			<input
				class="form-control"
				value={surname}
				onInput={event => (surname.value = event.currentTarget.value)}
			/>

			<button class="btn btn-primary btn-sm" onClick={() => count.value++}>
				click me!
			</button>
		</>
	);
};

Class Component

A Class Component is an older but sill valid approach that manages state and lifecycle methods within a class-based structure.

class ClassComponent extends Component {
	state = { count: 0 };

	increment = () => {
		this.setState(prev => ({ count: prev.count + 1 }));
	};

	render() {
		const { count } = this.state;
		return (
			<div>
				<p>Current count: {count}</p>
				<button onClick={this.increment}>+1</button>
			</div>
		);
	}
}

Higher-Order Component

A Higher-Order Component (HOC) is a function that takes a component and returns a new one, enhancing it with additional functionality or styling - like a wrapper.

const withStyle = WrappedComponent => {
	return props => (
		<div style={{ border: '2px solid black', padding: '8px' }}>
			<WrappedComponent {...props} />
		</div>
	);
};

const SimpleBox = ({ text }) => <div>{text}</div>;
export const BoxWithStyle = withStyle(SimpleBox);

Controlled Component

A Controlled Component keeps its form input values in sync with component state, giving you full control over user input behavior.

const ControlledInput = () => {
	const [value, setValue] = useState('');

	const handleChange = event => {
		setValue(event.target.value);
	};

	return (
		<div>
			<label>Your name:</label>
			<input type="text" value={value} onInput={handleChange} />
		</div>
	);
};

Forwarded Ref Component

A Forwarded Ref Components allows you to pass refs through components to access DOM elements or child components directly.

const InputWithRef = forwardRef((props, ref) => <input ref={ref} {...props} />);

Access ref in another component - i.e. set focus on input after clicking on a button

const RefAccessExample = () => {
	const inputRef = useRef(null);

	const handleFocus = () => {
		if (inputRef.current) {
			inputRef.current.focus();
		}
	};

	return (
		<InputWithRef ref={inputRef} />
		<button onClick={handleFocus}>focus input</button>
	);
};

Portal Component

A Portal Component allows rendering children into a different part of the DOM tree - often used for modals, tooltips or overlays.

Create a simple portal by importing createPortal and assign a DOM target to it.

import { createPortal } from 'preact/compat';

const Portal = ({ children }) => {
	return createPortal(children, document.body);
};

Use the Portal Component anywhere with custom content:

const App = () => {
	return (
		<div>
			<p>some text with normal DOM flow</p>

			<Potal>
				<div style={{ position: 'fixed', top: '20px', right: '20px' }}>
					this div is rendered as a portal
				</div>
			</Portal>
		</div>
	);
};

About the Author

Ardian Shala
Ardian Shala
I'm a freelance IT software architect focused on building efficient web solutions.
In my free time, I create utility libraries and share insights about modern web development.
Let´s connect