Frame
The State defines a list of user-defined components, but we need a way to render those components. But before we can do that, we need to know what to render.
Frame is essentially an instance of a component defined in the State and it outputs a View
For example, let's say we created a Frame for the Button component above with its enabled prop set to true. Then, its output View would be the following:
tsx{type: "TagView",tag: "button",props: {className: "bg-blue-900",},children: [{type: "TagView",tag: "text",props: {value: 0},},{type: "TagView",tag: "text",props: {value: "I'm enabled!"}}]}
The View is essentially the resulting static output of a component. The View of a Frame is recomputed when the component’s definition in the state is updated or when a side effect (ie: mutating a global variable) is performed.
Keeping the View updated
Apart from generating the View of a component from the state, a Frame is also responsible for keeping the View updated on any changes made to the state.
For example, let's say we were to update a prop to the above Button component's root <button> element:
tsx{type: "RekaComponent",props: [...],state: [...],template: {type: "TagTemplate",tag: "button",props: {"className": {type: "Literal",// value: "bg-blue-900",value: "bg-green-900" // <-- updated value}},children: [...]}}
Then, the resulting output will be updated accordingly:
tsx{type: "TagView",tag: "button",props: {className: "bg-green-900", // <-- updated},children: [...]}
Rendering
When we create a Frame for an instance of a component defined in the state, we now know what to render - the View. Now all that's left is - how to render the given View.
Given that the View is essentially a serializable JSON structure, we can easily build a renderer that takes the View and renders it in whatever framework we want. For example, we can easily create a React renderer like so:
tsxconst Renderer = ({ view }) => {if (props.view instanceof t.TagView) {if (props.view.tag === 'text') {return <span>{props.view.props.value}</span>;}return React.createElement(props.view.tag,props.view.props,props.view.children.map((child) => (<Renderer key={child.id} view={child} />)));}if (props.view instanceof t.RekaComponentView) {return props.view.render.map((r) => <Renderer key={r.id} view={r} />);}if (props.view instanceof t.ExternalComponentView) {return props.view.component.render(props.view.props);}if (props.view instanceof t.SlotView || props.view instanceof t.FragmentView) {return props.view.children.map((r) => <Renderer key={r.id} view={r} />);}if (props.view instanceof t.ErrorSystemView) {return (<div className="">Something went wrong. <br />{props.view.error}</div>);}return null;};