Assuming that by position, you mean Mounting HTML element like body, div or some CSS selector like '#mountElm', then you can export a render function like:
import { render, h } from 'preact';
// WidgetA is a Preact component.
// It could be functional or class component.
export function WidgetA(props) {
// Use props here
return (
<div>WidgetA</div>
);
}
// Render function for WidgetA
export function renderWidgetA(position, props) {
const renderElm = position instanceof HTMLElement
? position
: document.querySelector(position);
render(h(Component, props), renderElm);
}
When this file is bundled, it can be simply used like:
import { renderWidgetA } from './my-bundle.js';
renderWidgetA('body', { title: 'Hello world' });
You can follow a similar pattern to create multiple components. Further, you can simply extract the render function into a more generic variant.
Question 1: How to make the function available on the global window object?
To achieve, this you have two options:
- Use Webpack and specify
libraryTarget for the output. It could be umd or similar. Read more here.
- If you cannot use Webpack or forbidden from changing it, then at the end of the file, you can explicitly bind it to a global object.
Example:
window.myLib = { renderWidgetA };
// Usage
myLib.renderWidgetA('body', { /* some props */});
Question 2: What to do when a prop changes for a certain widget.
You have to make a change to the render function. It accepts the optional third parameter that you can set to true. So your function becomes:
export function renderWidgetA(position, props) {
const renderElm = position instanceof HTMLElement
? position
: document.querySelector(position);
// NOTE THE THIRD PARAM
render(h(Component, props), renderElm, true);
}
Once, you do that simply call renderWidgetA function whenever your props change. It is completely harmless. Just make sure that your position node remains the same across multiple re-rendering. Also, always remember that UI as a Function of State. VDOM will take of everything else for you.