Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add React component #255

Merged
merged 11 commits into from
May 3, 2024
Merged

Add React component #255

merged 11 commits into from
May 3, 2024

Conversation

trentfridey
Copy link
Contributor

@trentfridey trentfridey commented Apr 12, 2024

What

This PR adds the react-component package, which exports a <GenomeSpy /> React component. It also adds documentation on usage and an example in the embed-examples package.

Why

This component should make it is easier to get started with GS in an existing React application.

How

The component is a thin wrapper around the embed function. Its only rendered element is the container, whose ref is passed to the embed function. It has a spec prop for initialization, and a onEmbed prop that returns the JS api object, so the user has access to updateNamedData, etc.

Notes

As it currently stands, the spec is not a reactive prop, i.e. if someone decides to update the object passed to <GenomeSpy/>, this won't trigger an update of the visualization. They should use the existing API (as returned in onEmbed). Not sure if this would be obvious to a React dev, but I don't have an idea yet as to a better compromise.

Hope this makes sense (not sure if I configured the inter-package dependencies properly). Comments welcome.

@trentfridey trentfridey marked this pull request as ready for review April 17, 2024 04:34
@tuner
Copy link
Member

tuner commented Apr 17, 2024

Thanks, Trent!

I'll have a look at this today or tomorrow. Meanwhile, could you update package-lock.json to get tests running: https://github.com/genome-spy/genome-spy/pull/255/checks

Copy link
Member

@tuner tuner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems to work! I added some comments.

When it comes to changing the spec, etc., could we implement it in pretty much the same way as react-vega does? https://vega.github.io/react-vega/?path=/story/react-vega--vegalite

Thus, when the identity of the provided spec object changes, i.e., the user provides a new spec, the component destroys the existing GenomeSpy instance and calls embed function again with the new spec?

It would be convenient to allow dynamic data to be updated in a similar way. When the user provides a new data object (which maps dataset names to data arrays) through the data attribute, those dataset arrays that have a new identity would be updated using updateNamedData.

const [error, setError] = useState<string | undefined>()

useEffect(() => {
async function embedToDoc(container: HTMLDivElement | null, config: RootSpec) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not embedding to docs. Function name should be changed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, should be in 093b914

@@ -12,6 +12,7 @@
},
"dependencies": {
"@genome-spy/core": "^0.51.0",
"@genome-spy/react-component": "^0.51.0",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessary (?)

<meta charset="UTF-8" />
<link rel="stylesheet" href="style.scss" />
<title>React Component example</title>
<script type="module" src="/reactComponent.jsx"></script>
Copy link
Member

@tuner tuner Apr 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<script> should be at the end of body. To make it consistent with other examples.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in a514424

@@ -1,3 +1,6 @@
{
"compilerOptions": {
"jsx": "react"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A path entry to packages/react-component/src could be added here to fix typings. See the /tsconfig.json at the repo root.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in 1abffe2

}

export default function GenomeSpy ({ spec, onEmbed }: IGenomeSpyProps) {
const embedRef = useRef<HTMLDivElement>(null)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could containerRef be more specific?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, should be in 093b914

useEffect(() => {
async function embedToDoc(container: HTMLDivElement | null, config: RootSpec) {
try {
const api = await embed(container, config, { bare: true })
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the component is removed from the dom, embed api's finalize method should be called to ensure that all resources are released, possible listeners in the document root are removed, etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, should be in 093b914

],
}

const generateData = () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is overly complex for a simple example with static data. I would provide a flat, static array of objects.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fixed in 0ba4f7a

@tuner tuner linked an issue Apr 17, 2024 that may be closed by this pull request
@trentfridey
Copy link
Contributor Author

I'll have a look at this today or tomorrow. Meanwhile, could you update package-lock.json to get tests running: https://github.com/genome-spy/genome-spy/pull/255/checks

Sorry for being dense but I've looked at the workflow definition file and I'm not sure what I need to do here to get tests running.

@tuner
Copy link
Member

tuner commented Apr 30, 2024

Thanks, Trent. I'll have a look at this later this week.

@tuner tuner merged commit f676ff6 into genome-spy:master May 3, 2024
1 check failed
@tuner
Copy link
Member

tuner commented May 3, 2024

Thanks, @trentfridey! I merged this PR and made some fixes in 3389e5c. In particular, resolution of types is quite difficult to get right in a monorepo that uses JavaScript with typings in JSDoc.

I still need to fix the build & publishing steps in the react-component package. I'm a bit busy right now, but I hope to be able to do it next week.

I'd like to have a separate data property, which would also be reactive. However, I'll probably create a <genome-spy> web component at some point, and it should have equivalent reactive properties. They should be aligned so that both components behave in a similar way.

And congrats, you are the first contributor to this repo! 🍾

@tuner
Copy link
Member

tuner commented May 16, 2024

Hi @trentfridey!

I published new versions of GenomeSpy packages. The @genome-spy/react-component package is now available for use.

I also created a small test app to ensure that packaging, etc. works. It's here: https://github.com/genome-spy/genomespy-react-example

An again, thanks for the contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Make a React example and/or component
2 participants