Web components have a class based API
Is there a way to model using pure rescript? guess no, as there is no class construct equivalent
Is there a way to bind rescript to js class definitions?
Is there a way to model using pure rescript? guess no, as there is no class construct equivalent
Correct. There’s not a way to create classes in pure rescript.
Is there a way to bind rescript to js class definitions?
Sure. In the React component case, it’s pretty easy. Here’s an implementation of an ErrorBoundary that should work in the playground:
@@jsxConfig({ version: 4, mode: "automatic" })
module ErrorBoundary = {
%%raw(`
class ErrorBoundaryImpl extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: true };
}
componentDidCatch(error, info) {
// Example "componentStack":
// in ComponentThatThrows (created by App)
// in ErrorBoundary (created by App)
// in div (created by App)
// in App
console.log(error, info.componentStack);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return this.props.fallback;
}
return this.props.children;
}
}
`)
@react.component
external make: (
~fallback: React.element,
~children: React.element
) => React.element = "ErrorBoundaryImpl"
}
let badCall: () => 'a = %raw(`
() => { throw "Oh boy." }
`)
module ChildComponent = {
@react.component
let make = (~shouldError) => {
if shouldError {
badCall()
}
<div style={{color: "green"}}>
{React.string("All good here!")}
</div>
}
}
module App = {
@react.component
let make = () =>
<div>
<ErrorBoundary fallback={<div style={{color: "red"}}>{React.string("Never needed!")}</div>}>
<ChildComponent shouldError={false} />
</ErrorBoundary>
<ErrorBoundary fallback={<div style={{color: "red"}}>{React.string("An error was thrown here!")}</div>}>
<ChildComponent shouldError={true} />
</ErrorBoundary>
</div>
}
1 Like
Just tried out some stuff with web components a few months ago:
let define: options => unit = %ffi(`
function(options) {
const clazz = class extends HTMLElement {
constructor() {
super()
}
connectedCallback() {
if (this.attached) {
return;
}
this.attached = true;
this.shadowRoot.appendChild(options.render());
}
}
customElements.define(options.name, clazz)
}
`)
1 Like