State Decorator

The @State() decorator can be used to manage internal data for a component. This means that a user cannot modify this data from outside the component, but the component can modify it however it sees fit. Any changes to a @State() property will cause the components render function to be called again.

Example

This example makes use of State and Listen decorators. We define a class property called open and decorate it with @State. With the use of @Listener we respond to click events toggling the value of open.

import { Component, State, Listen, h } from '@stencil/core';

@Component({
  tag: 'my-toggle-button'
})

export class MyToggleButton {
  @State() open: boolean;

  @Listen('click', { capture: true })
  handleClick() {
    this.open = !this.open;
  }

  render() {
    return <button>
      {this.open ? "On" : "Off"}
    </button>;
  }
}

For more advanced use cases state can be a complex Type. In the below example we maintain a list of Todo type values.

import { State } from '@stencil/core';

type Todo = {
  done: boolean,
  description: string,
}

export class TodoList {

  @State() completedTodos: Todo[];

  completeTodo(todo: Todo) {
    // This will cause our render function to be called again
    this.completedTodos = [...this.completedTodos, todo];
  }
}

When to use?

Not all internal state might need to be decorated with @State(), in fact it's a good practice to avoid using it if you know for sure that the value will not change or that it does NOT need to trigger a re-rendering:

class Component {

  // If `cacheData` changes we don't want to rerender the component,
  // so we DON'T decorate it with @State
  cacheData = SOME_BIG_DATA;

  // If this state change we want to run render() again
  @State() value;
}
BackNext
Contributors