Working with Functional Components

Functional components are quite different to normal Stencil web components because they are a part of Stencil's JSX compiler. A functional component is basically a function that takes an object of props and turns it into JSX.

const Hello = props => <h1>Hello, {props.name}!</h1>;

When the JSX transpiler encounters such a component, it will take its attributes, pass them into the function as the props object, and replace the component with the JSX that is returned by the function.

<Hello name="World" />

Functional components also accept a second argument children.

const Hello = (props, children) => [
  <h1>Hello, {props.name}</h1>,
  children
];

The JSX transpiler passes all child elements of the component as an array into the function's children argument.

<Hello name="World">
  <p>I'm a child element.</p>
</Hello>

Stencil provides a FunctionalComponent generic type that allows to specify an interface for the component's properties.

// Hello.tsx

import { FunctionalComponent, h } from '@stencil/core';

interface HelloProps {
  name: string;
}

export const Hello: FunctionalComponent<HelloProps> = ({ name }) => (
  <h1>Hello, {name}!</h1>
);

When using a functional component in JSX, its name must start with a capital letter. Therefore it makes sense to export it as such.

There are a few major differences between functional components and class components. Since functional components are just syntactic sugar within JSX, they...

  • aren't compiled into web components,
  • don't create a DOM node,
  • don't have a Shadow DOM or scoped styles,
  • don't have lifecycle hooks,
  • are stateless.

When deciding whether to use functional components, one concept to keep in mind is that often the UI of your application can be a function of its state, i. e., given the same state, it always renders the same UI. If a component has to hold state, deal with events, etc, it should probably be a class component. If a component's purpose is to simply encapsulate some markup so it can be reused across your app, it can probably be a functional component (especially if you're using a component library and thus don't need to style it).

BackNext
Contributors