[フレーム]
Skip to main content
An OutSystems Company →
This is documentation for Stencil v3, which is no longer actively maintained.
For up-to-date documentation, see the latest version (v4.40).
Version: v3

Reactive Data

Stencil components update when props or state on a component change.

Rendering methods

When a props or state change on a component, the render() method is scheduled to run.

The Watch Decorator (@Watch())

@Watch() is a decorator that is applied to a method of a Stencil component. The decorator accepts a single argument, the name of a class member that is decorated with @Prop() or @State(). A method decorated with @Watch() will automatically run when its associated class member changes.

// We import Prop & State to show how `@Watch()` can be used on
// class members decorated with either `@Prop()` or `@State()`
import{Component,Prop,State,Watch}from'@stencil/core';

@Component({
tag:'loading-indicator'
})
exportclassLoadingIndicator{
// We decorate a class member with @Prop() so that we
// can apply @Watch()
@Prop() activated:boolean;
// We decorate a class member with @State() so that we
// can apply @Watch()
@State() busy:boolean;

// Apply @Watch() for the component's `activated` member.
// Whenever `activated` changes, this method will fire.
@Watch('activated')
watchPropHandler(newValue:boolean, oldValue:boolean){
console.log('The old value of activated is: ', oldValue);
console.log('The new value of activated is: ', newValue);
}

// Apply @Watch() for the component's `busy` member.
// Whenever `busy` changes, this method will fire.
@Watch('busy')
watchStateHandler(newValue:boolean, oldValue:boolean){
console.log('The old value of busy is: ', oldValue);
console.log('The new value of busy is: ', newValue);
}

@Watch('activated')
@Watch('busy')
watchMultiple(newValue:boolean, oldValue:boolean, propName:string){
console.log(`The new value of ${propName} is: `, newValue);
}
}

In the example above, there are two @Watch() decorators. One decorates watchPropHandler, which will fire when the class member activated changes. The other decorates watchStateHandler, which will fire when the class member busy changes.

When fired, the @Watch()'ed method will receive the old and new values of the prop/state. This is useful for validation or the handling of side effects.

info

The @Watch() decorator does not fire when a component initially loads.

Handling Arrays and Objects

When Stencil checks if a class member decorated with @Prop() or @State() has changed, it checks if the reference to the class member has changed. When a class member is an object or array, and is marked with @Prop() or @State, in-place mutation of an existing entity will not cause @Watch() to fire, as it does not change the reference to the class member.

Updating Arrays

For arrays, the standard mutable array operations such as push() and unshift() won't trigger a component update. These functions will change the content of the array, but won't change the reference to the array itself.

In order to make changes to an array, non-mutable array operators should be used. Non-mutable array operators return a copy of a new array that can be detected in a performant manner. These include map() and filter(), and the spread operator syntax. The value returned by map(), filter(), etc., should be assigned to the @Prop() or @State() class member being watched.

For example, to push a new item to an array, create a new array with the existing values and the new value at the end:

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

@Component({
tag:'rand-numbers'
})
exportclassRandomNumbers{
// We decorate a class member with @State() so that we
// can apply @Watch(). This will hold a list of randomly
// generated numbers
@State() randNumbers:number[]=[];

private timer:NodeJS.Timer;

// Apply @Watch() for the component's `randNumbers` member.
// Whenever `randNumbers` changes, this method will fire.
@Watch('randNumbers')
watchStateHandler(newValue:number[], oldValue:number[]){
console.log('The old value of randNumbers is: ', oldValue);
console.log('The new value of randNumbers is: ', newValue);
}

connectedCallback(){
this.timer=setInterval(()=>{
// generate a random whole number
const newVal =Math.ceil(Math.random()*100);

/**
* This does not create a new array. When stencil
* attempts to see if any Watched members have changed,
* it sees the reference to its `randNumbers` State is
* the same, and will not trigger `@Watch` or a re-render
*/
// this.randNumbers.push(newVal)

/**
* Using the spread operator, on the other hand, does
* create a new array. `randNumbers` is reassigned
* using the value returned by the spread operator.
* The reference to `randNumbers` has changed, which
* will trigger `@Watch` and a re-render
*/
this.randNumbers=[...this.randNumbers, newVal]
},1000)
}

disconnectedCallback(){
if(this.timer){
clearInterval(this.timer)
}
}

render(){
return(
<div>
randNumbers contains:
<ol>
{this.randNumbers.map((num)=><li>{num}</li>)}
</ol>
</div>
)
}
}

Updating an object

The spread operator should be used to update objects. As with arrays, mutating an object will not trigger a view update in Stencil. However, using the spread operator and assigning its return value to the @Prop() or @State() class member being watched will. Below is an example:

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

exporttypeNumberContainer={
val:number,
}

@Component({
tag:'rand-numbers'
})
exportclassRandomNumbers{
// We decorate a class member with @State() so that we
// can apply @Watch(). This will hold a randomly generated
// number.
@State() numberContainer:NumberContainer={ val:0};

private timer:NodeJS.Timer;

// Apply @Watch() for the component's `numberContainer` member.
// Whenever `numberContainer` changes, this method will fire.
@Watch('numberContainer')
watchStateHandler(newValue:NumberContainer, oldValue:NumberContainer){
console.log('The old value of numberContainer is: ', oldValue);
console.log('The new value of numberContainer is: ', newValue);
}

connectedCallback(){
this.timer=setInterval(()=>{
// generate a random whole number
const newVal =Math.ceil(Math.random()*100);

/**
* This does not create a new object. When stencil
* attempts to see if any Watched members have changed,
* it sees the reference to its `numberContainer` State is
* the same, and will not trigger `@Watch` or are-render
*/
// this.numberContainer.val = newVal;

/**
* Using the spread operator, on the other hand, does
* create a new object. `numberContainer` is reassigned
* using the value returned by the spread operator.
* The reference to `numberContainer` has changed, which
* will trigger `@Watch` and a re-render
*/
this.numberContainer={...this.numberContainer, val: newVal};
},1000)
}

disconnectedCallback(){
if(this.timer){
clearInterval(this.timer)
}
}

render(){
return<div>numberContainer contains: {this.numberContainer.val}</div>;
}
}

AltStyle によって変換されたページ (->オリジナル) /