Repository navigation
A Better Custom JS Interface #1001
Description
Current Situation
There are a couple problems with the current JS interface:
- Confusing to implement
- Not versioned
- Does not allow for components imported by other sources to be rendered as children
The last piece is a fairly significant blocker for allowing ReactPy to work seamlessly with JS since users may want to combine components from several different libraries together.
Proposed Actions
The new interface should allow custom JS modules to be implemented in the following way:
// inside my-component-lib.js
import React from "react";
import { ImportedElement } from "@reactpy/client";
// need to access all exports in this module (i think you can do self imports?)
import components import "./my-component-lib.js";
export bind(node) {
root = React.createRoot(node);
return {
version: 1,
renderVdom(model, context) =>
root.render(
<ImportedElement
model={model}
client={context.client}
components={components}
/>),
unmount: root.unmount,
}
}
export function MyComponent(props) {
...
}In typescript the module would conform to the following spec:
type ImportSource { bind: ( node: HTMLElement ) => ImportSourceBinding };
type ImportSourceBinding {
version: number;
renderVdom: (model: ReactPyVdom, context: { client: ReactPyClient }) => void;
unmount: () => void;
}This seems simpler to understand than the current bind() function that returns an object with the methods:
create(type, props, children)render(component)unmount().
Where components are constructed with create and then passed to render.
With that said, the simpler interface comes at the cost of requiring more effort to implement. This comes down to the fact that, ReactPy wouldn't do any work to help render the model. Presently, ReactPy will render props passed to the create function which has the benefit that, model.eventHandlers will have already been turned into usable callbacks.
The new interface would basically make infeasible to write simple examples like the "super simple chart" seen in the docs today without importing some utilities from @reactpy/client. On way to remedy that could be to all ImportSourceBinding to have a renderSimple function that is mutually exclusive with renderVdom. The renderSimple function could look something like this:
type ImportSourceBinding {
...
renderSimple?: (node: HTMLElement, type: string, props: { [key: string]: any }) => void;
}Where, as is the case currently, prop would contain realized callbacks that were rendered from model.eventHandlers. Import sources that have a renderSimple function instead of a renderVdom function would not support component children.
Activity
[-]A Better Custom JS Interface[/-][+][Draft] A Better Custom JS Interface[/+]Archmonger commentedon May 27, 2023
Let's schedule a meeting to talk through this interface and run some simulated development scenarios.
rmorshea commentedon May 27, 2023
I think I've been going about this from the wrong angle. If implementing the custom JS component interface is going to require that you import some utilities from
@reactpy/client, we can imagine utilities that would make doing so significantly easier:Archmonger commentedon Jun 4, 2023
We forgot to talk about how this bind API will play into the build system
nsosupport commentedon Jun 7, 2023
rmorshea commentedon Jul 17, 2023
This library seems perfect for what we're trying to do: https://github.com/samwillis/nodejs-pypi
Archmonger commentedon Jul 17, 2023
Not only that, but the nodsjs-bin PyPi package seems perfect for us to use for ReactPy Build.
himself65 commentedon Feb 26, 2024
Is there a good way that js side could call the python component? For example
will be into
Archmonger commentedon Feb 26, 2024
@himself65 That feature currently doesn't exist. If we developed some sort of compiling step, is it technically possible that feature could exist in the future. Especially since we've already proven ReactPy can run client-side via this prototype implementation.
If you wish to discuss this further, please create a post in GitHub discussions.
Allow generic ReactJS component bindings (fix reactive-python#1001)
[-][Draft] A Better Custom JS Interface[/-][+]A Better Custom JS Interface[/+]v2.0.0b5 (#1312)