New tool to use React with Observable

Hello!

I’ve created a notebook that provides some helpful tools to to create and render React components with Observable.

Here’s what it does:

  • There’s a jsx function that uses the htm library to allow you to use JSX-like syntax directly in Observable.

  • You can call render to render some JSX to the page

  • You can call component to create a component that maintains its identity even if values used by the component change. This is accomplished by storing the returned component object in a cache keyed by the original component’s source code.

  • I’ve also created wrappers for memo and forwardRef that use the same implementation

  • Finally, virtually all the React exports have been re-exported for easy use:

    import { jsx, component, render, useState } from '@j-f1/react'
    

    (You can still import the original React and ReactDOM objects if you like)

What do you think? Are there any fatal flaws with this method?

5 Likes

Super cool, I especially love the React-inspired secret constant name :slight_smile: - I’ll add a link from my React-related notebooks.

2 Likes

Note that this

htm = (await import('https://unpkg.com/htm@2.1.1?module')).default

doesn’t work in current Firefox (but should work at some point in the future).

Is that because it doesn’t support ES modules yet?

It can be made to work in Firefox 66 by setting javascript.options.dynamicImport to true in about:config: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Browser_compatibility

It looks like dynamic imports will be enabled by default in Firefox 67 (due to be released in May).

2 Likes

Would you be willing to add that information to the notebook in the form of a suggestion?

I’ve just updated the notebook:

  • I’ve removed the dynamic import call.

  • The internal API has mostly been rewritten.

  • The render function now has support for viewof:

    viewof foo = render(({ useSetter }) => {
      const [text, setText] = useState('')
      useSetter(text)
      return jsx`
        <input
          type="text"
          placeholder="..."
          value=${text}
          onChange=${event => setText(event.target.value)}
        />
      `
    })
    
    foo // is the value of the text input
    
1 Like

Your notebook is awesome, Jed! Thank you.

I found the notebook days ago, but just found this forum thread, so I was missing a bit of context. Also, I was missing some essential bits of knowledge, so I had a little trouble understanding everything until I educated myself. Could you add some more explanatory prose to the notebook?

I was able to port one of my React Codepens using your code. My notebook may serve as a “broad and shallow” example for someone (perhaps too broad).

3 Likes

Thanks for the feedback @vorth! I added a little more explanation around htm syntax, created a super basic “Hello world” example, reworded the docs a little bit, and linked to your example notebook.

Feel free to send suggestions in the notebook if you have any specific ideas for changes!

4 Likes