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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@yz-dev/react-dynamic-module

v0.2.0

Published

A powerful React component for dynamically loading premium or optional modules from a script URL with dependency injection.

Readme

React Dynamic Module

npm version license creator

The definitive solution for dynamically loading React components from external scripts. A powerful, modern toolkit for building modular applications, micro-frontends, and optional, dynamically-loaded features.


✨ At a Glance

Instantly understand the power and type safety of both the hook and the component.

The Hook (For full control)

import { useDynamicModule } from '@yz-dev/react-dynamic-module';
import type { MyComponentProps } from 'my-component-types'; // Your component's props

const { status, as: MyComponent } = useDynamicModule<MyComponentProps>({
  src: '/modules/my-component.js',
  from: 'MyModule',
  import: 'MyComponent'
});

// Render it with full type safety and autocompletion.
if (MyComponent) {
  return <MyComponent someTypedProp="value" />;
}

The Component (For drop-in simplicity)

import { DynamicModule } from '@yz-dev/react-dynamic-module';
import type { MyComponentProps } from 'my-component-types';

<DynamicModule<MyComponentProps>
  src="/modules/my-component.js"
  from="MyModule"
  import="MyComponent"
  // Pass props directly with full type safety.
  someTypedProp="value"
/>

🔥 Hot as Hell: Why You Need This

Tired of complex private package setups that block contributors? Need to lazy-load a feature that isn't part of your main bundle? This is the definitive solution.

  • 💎 True Optional Modules: Load modules from a URL. If the module is missing, your app will not crash. It gracefully renders a fallback. Perfect for open-source apps with optional or external add-ons.
  • 🚀 Solves the "Duplicate React" Problem: Uses a robust dependency injection pattern to ensure the dynamically loaded module shares your host application's instance of React, preventing cryptic useState errors.
  • 🔒 Full Type Safety & Autocompletion: This is the magic. Use TypeScript generics (<MyComponentProps>) to get full, compile-time type checking and autocompletion for the props of your dynamically loaded component. No more any props.
  • 🛡️ Bulletproof & Graceful: A fetch pre-flight check prevents 404s or server errors from causing uncatchable exceptions.
  • 💉 Powerful Dependency Injection: Securely provide the loaded script with any dependencies it needs from the host application (React, ReactDOM, MUI, etc.).
  • ✌️ Dual API: Your Choice of Power or Simplicity. The library exports both a powerful hook (useDynamicModule) for maximum control and a simple component (<DynamicModule>) for maximum convenience.

📦 Installation

# Using yarn
yarn add @yz-dev/react-dynamic-module

# Using pnpm
pnpm add @yz-dev/react-dynamic-module

# Using npm
npm install @yz-dev/react-dynamic-module

⚙️ API & Usage

You have two ways to use this library, depending on your needs.

1. The Hook: useDynamicModule (For Full Control)

Use the hook when you need to know the loading status before rendering your UI, for example, to conditionally show a button that opens the module.

import { useDynamicModule } from '@yz-dev/react-dynamic-module';
import type { MyComponentProps } from 'my-component-types'; // Types from a shared package or stub
import { Button, Dialog, CircularProgress } from '@mui/material';

const MyFeature = () => {
  const [open, setOpen] = useState(false);

  const { status, as: MyComponent } = useDynamicModule<MyComponentProps>({
    src: '/modules/my-component.js',
    from: 'MyModule',
    import: 'MyComponent',
  });

  // Don't render the trigger button if the module isn't available
  if (status === 'unavailable' || status === 'checking') {
    return null;
  }

  return (
    <>
      <Button onClick={() => setOpen(true)}>Open Optional Feature</Button>
      <Dialog open={open} onClose={() => setOpen(false)}>
        {status === 'available' && MyComponent ? (
          <MyComponent someTypedProp="value" />
        ) : (
          <CircularProgress />
        )}
      </Dialog>
    </>
  );
};

Hook Return Value

| Property | Type | Description | | ---------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------- | | status | 'checking' \| 'loading' \| 'available' \| 'unavailable' | The current loading state of the module. | | as | React.ComponentType<P> \| null | If the status is available, this will be the loaded React component. Otherwise, it will be null. |

2. The Component: <DynamicModule /> (For Simplicity)

Use the component when you want a simple, declarative, "drop-in" solution.

import { DynamicModule } from '@yz-dev/react-dynamic-module';
import type { MyComponentProps } from 'my-component-types';
import { CircularProgress, Typography } from '@mui/material';

const MyFeature = (props) => {
  return (
    <DynamicModule<MyComponentProps>
      // --- Core Props ---
      src="/modules/my-component.js"
      from="MyModule"
      import="MyComponent"
      
      // --- Optional ---
      loadingUi={<CircularProgress />}
      errorUi={<Typography color="error">Feature Not Available.</Typography>}

      // --- Pass-through Props for the loaded component (fully type-safe!) ---
      {...props}
    />
  );
};

Component Props

| Prop | Type | Required | Description | | -------------- | ---------------------------------- | -------- | ------------------------------------------------------------------------------------------------------- | | src | string | Yes | The public path to the JavaScript module to load. | | from | string | Yes | The name of the global variable the script will attach its exports to (e.g., window.MyModule). | | import | string | Yes | The name of the exported component property on the global variable (e.g., MyModule.MyComponent). | | loadingUi | React.ReactNode | No | A component to render while the module is loading. | | errorUi | React.ReactNode | No | A component to render if the module fails to load. | | dependencies | Record<string, any> | No | An object of dependencies to inject into the window scope. React and ReactDOM are always included. | | onError | (error: Error) => void | No | A callback fired if any error occurs during loading. | | ...rest | any | No | All other props are passed directly to the successfully loaded component. |

🛠️ Building a Compatible Module (Example with Vite)

To create a script that can be loaded by this library, build it as an iife (Immediately Invoked Function Expression) and externalize its peer dependencies.

vite.config.ts for the module you want to load:

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { fileURLToPath, URL } from 'node:url';

export default defineConfig({
  plugins: [react()],
  define: { 'process.env.NODE_ENV': JSON.stringify('production') },
  build: {
    lib: {
      entry: fileURLToPath(new URL('./src/index.ts', import.meta.url)),
      name: 'MyModule', // This must match the 'from' prop
      formats: ['iife'],
      fileName: () => `my-module.js`,
    },
    rollupOptions: {
      external: ['react', 'react-dom'],
      output: {
        globals: {
          'react': 'React',
          'react-dom': 'ReactDOM',
        },
        exports: 'named',
      },
    },
  },
});

src/index.ts for the module:

export { MyComponent } from './components/MyComponent'; // This must match the 'import' prop

🤝 Contributing

Contributions are welcome! If you have a feature request, bug report, or want to contribute to the code, please feel free to open an issue or submit a pull request.