Render props — это паттерн, позволяющий компоненту управлять логикой и состоянием, передавая управление рендерингом другому компоненту через функцию. В контексте Stencil этот подход особенно полезен для создания повторно используемых компонентов с высокой степенью кастомизации.
В Stencil компонент описывается с помощью класса и декораторов, таких
как @Component, @Prop, @State и
@Event. Паттерн render props строится вокруг передачи
функции через @Prop, которая принимает текущее состояние
компонента и возвращает JSX для рендера.
Ключевые моменты:
@Prop() может быть функцией, которая управляет
рендерингом внутреннего состояния.@State() хранит локальное состояние, которое может быть
передано в render prop.import { Component, h, Prop, State } from '@stencil/core';
@Component({
tag: 'counter-render-prop',
shadow: true
})
export class CounterRenderProp {
@State() count: number = 0;
@Prop() render: (count: number, increment: () => void) => any;
increment = () => {
this.count += 1;
}
render() {
return this.render(this.count, this.increment);
}
}
В этом примере:
count хранит текущее значение счетчика.increment — метод увеличения счетчика.render — функция, переданная через @Prop,
которая принимает count и increment и
возвращает JSX для рендера.<counter-render-prop
render={(count, increment) => (
<div>
<p>Текущее значение: {count}</p>
<button onCl ick={increment}>Увеличить</button>
</div>
)}
></counter-render-prop>
Такой подход позволяет полностью контролировать отображение компонента, используя внешнюю логику и стили, не изменяя внутреннюю реализацию.
Stencil предоставляет хук @Watch для отслеживания
изменений @Prop и @State. Render props могут
использовать эти изменения для динамического рендеринга.
import { Component, h, Prop, State, Watch } from '@stencil/core';
@Component({
tag: 'timer-render-prop',
shadow: true
})
export class TimerRenderProp {
@State() time: number = 0;
@Prop() render: (time: number) => any;
intervalId: any;
componentDidLoad() {
this.intervalId = setInterval(() => this.time += 1, 1000);
}
disconnectedCallback() {
clearInterval(this.intervalId);
}
render() {
return this.render(this.time);
}
}
Этот компонент может быть использован так:
<timer-render-prop
render={(time) => <p>Прошло секунд: {time}</p>}
></timer-render-prop>
Render props обеспечивают высокую степень гибкости и позволяют:
@State и @Watch можно
создавать динамические и реактивные компоненты, которые
реагируют на изменения данных без переписывания JSX внутри самого
компонента.Render props в Stencil дают возможность создавать мощные, гибкие и переиспользуемые компоненты, сохраняя при этом реактивность и модульность, присущие веб-компонентам.