DOM Renderingchevron_right
Custom Rendererschevron_right
An advanced type of custom plugins are component processors. They are not directly used by renderers, but component plugins use them to customize functionalities of components.
1linkabstract class ComponentProcessor<Node, Renderer> extends Plugin<Node, Renderer> {
2link abstract process(
3link provide: (provision: ComponentProvision) => void, // --> can provide data / hooks for the component
4link post: (processor: ComponentPostProcessor<Node>) => void, // --> can post-process the nodes created by the component
5link component: ComponentData, // --> the component data (tag, props and children)
6link ): void;
7link}
Example:
1linkimport { ComponentProcessor } from 'render-jsx/component';
2linkimport { RendererLike } from 'render-jsx';
3link
4link
5linkexport class Theme<Node>
6link extends ComponentProcessor<Node, RendererLike<Node>> {
7link
8link constructor(readonly color: string) {
9link super();
10link }
11link
12link priority() { return ComponentProcessor.PriorityFallback; }
13link
14link process(provide) {
15link provide({ // --> provide data/hooks to components in form of key/values
16link color: this.color // --> this translates to `this.color` in functional components
17link });
18link }
19link}
1linkimport { CommonDOMRenderer } from 'render-jsx/dom';
2linkimport { Theme } from './theme.plugin';
3link
4link
5linkexport function MyComp(_, renderer) {
6link return <button style={`background: ${this.color}`}>Hola!</button>; // --> `this.color` exists because of the processor
7link}
8link
9linkconst renderer = new CommonDOMRenderer().plug(() => new Theme<Node>('#f7aa00'));
10link
11linkrenderer.render(<MyComp/>).on(document.body);
Plugins extending ComponentPlugin
class can enable new types of components. For example,
the following plugin provides support for simple class-based components:
1linkimport { RendererLike } from 'render-jsx';
2linkimport { ComponentPlugin } from 'render-jsx/component/plugins';
3link
4link
5linkexport abstract class Component<Node, Renderer=RendererLike<Node>> { // --> a base class for our components
6link static __COMP_CLASS_BASE__ = true; // --> this allows us to check if given tag is a class extending this base class
7link
8link constructor(
9link protected props, // --> collect given props
10link protected children, // --> collect the children
11link protected renderer, // --> collect the renderer
12link protected provision // --> collect additional provisions
13link ) {}
14link
15link abstract render(renderer: Renderer); // --> this will be invoked for rendering stuff
16link}
17link
18link
19linkexport class ClassComponentPlugin<Node> // --> so our plugin is generic towards node type
20link extends ComponentPlugin<Node, RendererLike<Node>> { // --> and can work with any renderer
21link
22link priority() { return ComponentPlugin.PriorityMax; }
23link
24link match(component) { // --> determines if given component data match this plugin
25link return typeof component.tag === 'function' // --> check if the tag is a function (constructor)
26link && component.tag.__COMP_CLASS_BASE__; // --> check if it is a class extending our base component class
27link }
28link
29link createComponent(component, provision) {
30link return new component.tag( // --> invoke the constructor
31link component.props, // --> give it the props
32link component.children, // --> give it the children
33link this.renderer(), // --> give it the plugged in renderer
34link provision // --> give it the additional provisions
35link ).render(this.renderer()); // --> call its render
36link }
37link}
1linkimport { CommonDOMRenderer } from 'render-jsx/dom';
2linkimport { Component, ClassComponentPlugin } from './class-comp.plugin';
3link
4linkclass MyComp extends Component<Node> {
5link render(renderer) {
6link return <div>Hellow {this.props.name}!</div>
7link }
8link}
9link
10linkconst renderer = new CommonDOMRenderer()
11link .plug(() => new ClassComponentPlugin<Node>());
12link
13linkrenderer.render
14link (<MyComp name='World'/>
15link).on(document.body);