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

@just-web/react

v9.0.4

Published

Supporting library for using @just-web with React

Downloads

17

Readme

@just-web/react

NPM version NPM downloads

@just-web/react provides the features needed to use just-web app with React.

Install

# npm
npm install @just-web/react

# yarn
yarn add @just-web/react

# pnpm
pnpm install @just-web/react

#rush
rush add -p @just-web/react

Usage

We will be focusing on how to use just-web app with React here.

If you want to know more about just-web app, you can check out the documentation of @just-web/app.

Following the example from @just-web/app, let's make the sing-along app into a React app.

Let's start with a simple example: a SPA.

To create a React SPA, you need two things from @just-web/react:

  • <JustAppProvider/>: the React context provider for JustApp.
  • useJustAppContext(): the React context hook to get the JustApp instance.
import { JustAppProvider } from '@just-web/react'
import ReactDOM from 'react-dom'
import { YourComponent } from './your_component'
import { singAlongApp } from './sing_along_app'

void (async () => {
  const app = await singAlongApp.with(reactGizmo).create()

  ReactDOM.render(
    <JustAppProvider value={app}>
      <YourComponent />
    </JustAppProvider>,
    document.getElementById('root')
  )
})()

// your_component.tsx
import { useJustAppContext } from '@just-web/react'
import type { SingAlongApp } from './sing_along_app'

export function YourComponent() {
  const app = useJustAppContext<SingAlongApp>()

  return (
    <div>
      <MusicPlayer start={() => app.miku.sing()} />
    </div>
  )
}

For Micro Frontends (MFEs), just JustAppProvider and useJustAppContext() may not be sufficient. Especially if you have components from different MFEs intertwined together.

In that case, you will also need:

  • createJustAppContext(): to create a React context for each MFE.
  • reactGizmo: to register the specific React context for each MFE.

In the example below, we have two MFEs: miku and rin.

Each of them is a MFE with its own JustApp instance.

They need to add reactGizmo, and register their own React context.

They are doing it differently to show two different ways of doing it.

const MikuAppContext = createJustAppContext<MikuApp>()
const mikuApp = await singAlongApp.with(reactGizmo)
  .create(app => app.react.providers.register(({ children }) => (
    <MikuAppContext.Provider value={app}>
      {children}
    </MikuAppContext.Provider>
  )))

const RinAppContext = createJustAppContext<RinApp>()
const rinAppIncubator = singAlongApp.with(reactGizmo)
  .init(app => app.react.providers.register(({ children }) => (
    <RinAppContext.Provider value={app}>
      {children}
    </RinAppContext.Provider>
  )))
const rinApp = await rinAppIncubator.create()

Then, in the React app, you can use the JustAppProvider for both mikuApp and rinApp, and they will work together.

ReactDOM.render(
  <JustAppProvider value={mikuApp}>
    <MikuSinging />
    <JustAppProvider value={rinApp}>
      <MikuDancing />
      <RinSinging />
    </JustAppProvider>
  </JustAppProvider>,
  document.getElementById('root')
)

Inside your components, you can still use useJustAppContext() with the JustAppContext you have created to get your specific app.

import { useJustAppContext } from '@just-web/react'
import { MikuAppContext } from './miku_app'

export function MikuSinging() {
  const app = useJustAppContext(MikuAppContext)

  return (
    <div>
      <MusicPlayer start={() => app.miku.sing()} />
    </div>
  )
}

Alternatively, you can use <MikuAppContext.Provider> or <RinAppContext.Provider> too, but typically there is no need to do so. In fact, you can keep them off your package exports.

The host app only need the mikuApp, rinApp, and the JustAppProvider and everything will work.

useStore

useStore() Allows you to use store from @just-web/states.

It is similar to useState() in React, but work on a store instead of a local state.

import { createStore } from '@just-web/states'
import { useStore } from '@just-web/react'

const store = createStore({ counter: 0 })

const Component = () => {
  const [counter, setCounter] = useStore(
    store,
    // get which part of the store to use as state
    s => s.counter,
    // updateStore when state changes
    s=>{ s.counter = counter }
  )

  return <div>{counter}</div>
}

useStoreContext

useStore() is useful to consume an app-level store:

// from another file
import { store } from './store'

// or create at the module scope
const store = createStore(...)

const Component = () => {
  const [] = useStore(store, ...)
}

But it doesn't work well if we want to have a local store that live and die with the DOM.

In React, that's when you can use createContext() and useContext().

Here, we can use createStoreContext() and useStoreContext() to achieve the same thing with Store.

And the usage is much simpler and efficient thanks to the underlying immer implementation.

import { createStoreContext, useStoreContext } from '@just-web/react'
import { createStore } from '@just-web/states'

type YourStore = { counter: number }

const YourContext = createStoreContext<YourStore>() // no default value

const YourProvider = (props) => {
  const store = createStore<YourStore>({ counter: 0 })
  return <YourContext.Provider value={store} {...props}/>
}

const YourConsumer = () => {
  const [counter, setCounter] = useStoreContext(
    YourContext,
    s => s.counter,
    (s, v) => { s.counter = v }
  )

  return (
    <>
      <div>counter: {counter}</div>
      <button onClick={() => setCounter(counter + 1)}>Increment</button>
    </>
  )
}

reactGizmo

As seen in the example above, reactGizmo provides a react.providers where you can register React context providers.

You can use it to add other providers to the app.

For example, i18n, theme, etc.

import { createApp } from '@just-web/app'
import reactPlugin, { AppContextProvider } from '@just-web/react'

function YourApp() {
  const app = createApp({...}).extned(reactPlugin)
  app.react.providers.register(({ children }) => <YourProvider {...}>{children}</YourProvider>)

  return (
    <JustAppProvider value={app}>
      ...
    </JustAppProvider>
  )
}

The providers will be added to the app in the order they are registered, inside the <JustAppProvider>.

This allows any gizmo to add their needed providers to the app, without having the app to know about them.