npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-solid-bridge

v1.0.1

Published

Render Solid.js components in React.js and visa versa.

Downloads

92

Readme

React to Solid to React Bridging

Render Solid.js components in React.js and visa versa.

This library allows you to even render React children in Solid components rendered by React and retain both state and context!

What works today

Working

React -> Solid -> React -> Solid -> ...

Works but needs testing

Solid -> React -> Solid

Incomplete

Solid -> React -> Solid -> React -> ...

NOTE: While context works in both Solid and React, their contexts aren't shared. You have to create a Solid context provider and pass it props from the React context if you want to keep them in sync. Typically, you can do this by passing props through useContext in React to Solid components.

How to Use

For rendering Solid components in React apps, you have to import the provider component: ReactToSolidBridgeProvider.

From there, it has multiple APIs:

  1. convertToReactComponent higher-order component (easiest).
  2. ReactToSolidBridge with the solidComponent prop (medium).
  3. ReactToSolidBridge with the getSolidComponent prop (confusing).

You can import these like so:

import {
  convertToReactComponent,
  ReactToSolidBridge,
  ReactToSolidBridgeProvider,
} from 'react-solid-bridge'

ReactToSolidBridgeProvider

You'll wrap either your entire app or the part that needs to render Solid.js components in ReactToSolidBridgeProvider. Ideally, this would be at the top-level of your app.

convertToReactComponent

convertToReactComponent is a friendly wrapper around ReactToSolidBridge. It allows you to convert Solid components into React components, but some things won't work right if they have weird APIs (like the Routes component from solid-app-router).

NOTE: This does not work with Solid context providers: Context.Provider. If you have one of those, you'll have to use ReactToSolidBridge with the getSolidComponent prop.

Typically, this higher-order component will work without issue.

You use it like so:

import {
  Cube as SolidCube,
  Horse as SolidHorse,
} from 'phosphor-solid'
import {
  convertToReactComponent,
  ReactToSolidBridgeProvider,
} from 'react-solid-bridge'

const Cube = convertToReactComponent(SolidCube)
const Horse = convertToReactComponent(SolidHorse)

const App = () => (
  <ReactToSolidBridgeProvider>
    <Cube />
    <Horse />
  </ReactToSolidBridgeProvider>
)

export default App

Once you've done this, they'll function like regular React components.

ReactToSolidBridge

ReactToSolidBridge is a React component that renders Solid components and allows rendering React children in those Solid components.

This works because ReactToSolidBridgeProvider renders a Solid app into a div element that it creates. From there, Solid components are portalled into a div rendered by ReactToSolidBridge.

If this sounds complicated, it is. Thankfully, that's all been black-boxed, and you shouldn't have to worry about it.

Medium Difficulty API

This is the same API used by the convertToReactComponent higher-order component. It's highly recommended to use that function instead.

This example shows rendering both React children and props from React into a Solid component.

import {
  useCallback,
  useState,
} from 'react'
import {
  ReactToSolidBridge,
  ReactToSolidBridgeProvider,
} from 'react-solid-bridge'

import ReactComponent from './ReactComponent.jsx'
import SolidComponent from '../solid/SolidComponent.jsx'

const App = () => {
  const [
    count,
    setCount,
  ] = (
    useState(
      0
    )
  )

  const incrementCount = (
    useCallback(
      () => {
        setCount((
          localCount,
        ) => (
          localCount
          + 1
        ))
      },
      [],
    )
  )
  
  return (
    <ReactToSolidBridgeProvider>
      <ReactToSolidBridge
        props={{
          count,
          incrementCount,
        }}
        solidComponent={SolidComponent}
      >
        <ReactComponent />
      </ReactToSolidBridge>
    </ReactToSolidBridgeProvider>
  )
}

Customizable, but confusing and sometimes required, API

NOTE: When creating a Solid component, children needs to be a getter, and it's highly recommended to do that with all non-function props as well.

If this is a local component, meaning you have Webpack configured to render both React and Solid JSX in the bundle, and this exists in your repository, then you only need children to be a getter.

This example details using the customizable, but confusing API for ReactToSolidBridge and how you can render multiple Solid components next to each other this way.

This API is not recommended unless you have a use case. If the other APIs throw errors, then this one might be right for you.

import {
  useCallback,
  useState,
} from 'react'
import {
  ReactToSolidBridge,
  ReactToSolidBridgeProvider,
} from 'react-solid-bridge'

import ReactComponent from './ReactComponent.jsx'
import SolidComponent1 from '../solid/SolidComponent1.jsx'
import SolidComponent2 from '../solid/SolidComponent2.jsx'

const App = () => {
  const [
    count,
    setCount,
  ] = (
    useState(
      0
    )
  )

  const incrementCount = (
    useCallback(
      () => {
        setCount((
          localCount,
        ) => (
          localCount
          + 1
        ))
      },
      [],
    )
  )
  
  return (
    <ReactToSolidBridgeProvider>
      <ReactToSolidBridge
        props={{
          count,
          incrementCount,
        }}
        getSolidComponent={({
          getChildren,
          props,
        }) => ([
          SolidComponent1({
            get children() {
              return getChildren()
            },
            get count() {
              return (
                props
                .count()
              )
            },
          })
          SolidComponent2({
            incrementCount: (
              props
              .incrementCount
            ),
          })
        ])}
      >
        <ReactComponent />
      </ReactToSolidBridge>
    </ReactToSolidBridgeProvider>
  )
}

Shared Context Example

NOTE: When creating a Solid component, children needs to be a getter, and it's highly recommended to do that with all non-function props as well.

This example shows rendering React children in Solid along with both React and Solid components having access to a shared context.

import {
  ReactToSolidBridge,
  ReactToSolidBridgeProvider,
} from 'react-solid-bridge'

import ReactComponent from './ReactComponent.jsx'
import ReactContext from './ReactContext.js'
import ReactContextConsumer from './ReactContextConsumer.jsx'
import ReactContextProvider from './ReactContextProvider.jsx'
import ReactStatefulComponent from './ReactStatefulComponent.jsx'
import SolidComponent from '../solid/SolidComponent.jsx'
import SolidContext from '../solid/SolidContext.js'
import SolidContextConsumer from '../solid/SolidContextConsumer.jsx'
import SolidStatefulComponent from '../solid/SolidStatefulComponent.jsx'

const App = () => (
  <ReactToSolidBridgeProvider>
    <ReactContextProvider>
      <ReactContextConsumer />

      <ReactContext.Consumer>
        {
          ({
            count,
            incrementCount,
          }) => (
            <ReactToSolidBridge
              getSolidComponent={({
                getChildren,
                props,
              }) => (
                SolidContext
                .Provider({
                  get children() {
                    return (
                      SolidComponent({
                        children: getChildren,
                      })
                    )
                  },
                  value: {
                    count: (
                      props
                      .count
                    ),
                    incrementCount: (
                      props
                      .incrementCount
                    ),
                  },
                })
              )}
              props={{
                count,
                incrementCount,
              }}
            >
              <ReactContextConsumer />

              <ReactComponent>
                <ReactToSolidBridge
                  getSolidComponent={({
                    getChildren,
                    props,
                  }) => ([
                    SolidContextConsumer(),
                    SolidStatefulComponent({
                      get count() {
                        return (
                          props
                          .count()
                        )
                      },
                    }),
                    getChildren(),
                  ])}
                  props={{
                    count,
                  }}
                >
                  <ReactContextConsumer />
                  <ReactStatefulComponent
                    count={count}
                  />
                </ReactToSolidBridge>
              </ReactComponent>
            </ReactToSolidBridge>
          )
        }
      </ReactContext.Consumer>
    </ReactContextProvider>
  </ReactToSolidBridgeProvider>
)

export default App

Things to keep in mind

Rendering React and Solid apps side-by-side

When using Solid in side of React or visa versa, this works great if you're using a library.

If you want to run both libraries side-by-side, you need to have separate Babel configs for React and Solid JSX. While both are JSX, they require different pragmas.

That's beyond the scope of this library, but the source code of react-solid-bridge actually achieves this feat using a single Webpack config.