Share & Replace React components

Learn how to share UI components between modules and how to override them using JopiJS's unique priority system.

Overview

In traditional frameworks, sharing a component usually means importing it from a specific file path. JopiJS introduces a more powerful concept: Isomorphic Component Sharing.

Instead of importing from a specific module, you import from a virtual namespace. This allows any module to provide, extend, or completely replace a component without changing a single line of code in the rest of the application.

In this guide, you will learn how to:

  • Share a React component using the @alias/ui/ folder.
  • Import shared components using module-agnostic paths.
  • Override an existing component from another module.

1. Sharing a Component

To make a React component available to other modules, place it in your module's @alias/ui/ directory. The folder name becomes the component's Shared Name.

Standard Structure:

src/ mod_my_theme/
└── @alias/
    └── ui/
        └── Button/         # The "Shared Name"
            └── index.tsx   # The component (must use default export)
src/mod_my_theme/@alias/ui/Button/index.tsx
export default function Button({ children }: { children: React.ReactNode }) {
    return <button className="btn-primary">{children}</button>;
}

2. Using Shared Components

When you want to use a shared component, you don't need to know which module provides it. You simply import it from the @/ui/ virtual path.

Using the component in any module
// The path is always "@/ui/[SharedName]"
import Button from "@/ui/Button";

export default function MyPage() {
    return <Button>Click Me</Button>;
}

The "Seamless" Advantage:
If you decide to replace your Button with a version from a different module later, you don't have to update your imports. JopiJS handles the redirection automatically.


3. Replacing a Component (Overriding)

The real power of this system comes when you want to customize a component from a third-party module (like a theme module) without modifying its source code.

How it works:

  1. Identify the Shared Name of the component you want to replace.
  2. Create a folder with the same name in your own module.
  3. Add a high.priority file to your folder.

Visual Example:

Imagine mod_my_template provides a ProductCard, but you want a different design in your project.

Project Structure
src/
├── mod_my_template/
│   └── @alias/ui/ProductCard/
│       ├── index.tsx
│       └── default.priority     # The original version
└── mod_my_project/
    └── @alias/ui/ProductCard/   # Same Shared Name!
        ├── index.tsx            # Your custom design
        └── high.priority        # Force JopiJS to use THIS version

4. Why Use This System?

A. Non-Destructive Customization

You can "patch" a library or a theme without forking it. This makes updates simple: just git pull the library, and your local overrides remain intact.

B. Theming

Building a "Dark Mode" or a "Refined Design" module becomes trivial. You just override the specific UI atoms (Button, Card, Input) in a new module, and the whole application updates instantly.

C. A/B Testing

You can easily swap entire UI sections by enabling or disabling modules, as JopiJS will automatically fall back to the next available priority level.

Pro Tip: To quickly "disable" an override and see the original version, simply rename your module folder by adding an underscore (e.g., _mod_my_project).