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)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.
// 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:
- Identify the Shared Name of the component you want to replace.
- Create a folder with the same name in your own module.
- Add a
high.priorityfile to your folder.
Visual Example:
Imagine mod_my_template provides a ProductCard, but you want a different design in your project.
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 version4. 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).