0Pricing
React Academy · Lesson

Shared State & Routing Between MFEs

Share a global event bus or context across micro-frontends and coordinate client-side routing.

Shared State & Routing Between MFEs is a free React Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the React Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

The State Sharing Challenge

Micro-frontends in different bundles cannot directly share React state or context. They need alternative strategies: custom events, shared stores, URL, or a pub/sub event bus.

Browser Custom Events

Use the browser's CustomEvent API as a simple event bus between micro-frontends without coupling them together.

// Remote emits:
window.dispatchEvent(new CustomEvent('cart:add', { detail: { productId: '123' } }));

// Host listens:
useEffect(() => {
  const handler = (e: CustomEvent) => addToCart(e.detail.productId);
  window.addEventListener('cart:add', handler);
  return () => window.removeEventListener('cart:add', handler);
}, []);

Shared Event Bus Library

A tiny pub/sub library shared (via Module Federation or a URL-loaded singleton) gives a typed event bus accessible to all MFEs.

// Singleton event bus
const bus = {
  listeners: new Map<string, Function[]>(),
  emit(event: string, data: unknown) {
    this.listeners.get(event)?.forEach(fn => fn(data));
  },
  on(event: string, fn: Function) {
    if (!this.listeners.has(event)) this.listeners.set(event, []);
    this.listeners.get(event)!.push(fn);
    return () => this.off(event, fn);
  },
  off(event: string, fn: Function) {
    const list = this.listeners.get(event) || [];
    this.listeners.set(event, list.filter(f => f !== fn));
  },
};
export default bus;

URL as Shared State

The URL (path + query params) is naturally shared between all MFEs. Use it for navigation state like selected item, active tab, or filter values.

// Remote reads from URL:
const params = new URLSearchParams(window.location.search);
const productId = params.get('product');

// Remote navigates via history API (or exposes a navigate callback from host):
window.history.pushState({}, '', '/products?product=456');

Routing Architecture

Typically the shell/host app owns the top-level router. Remote micro-frontends receive the current path and a navigate callback as props.

// Host passes routing control to remote:
<RemoteProductsApp
  basepath="/products"
  navigate={(path) => router.push(path)}
/>

// Remote uses basepath for its internal router:
<BrowserRouter basename={basepath}>
  <Routes>...</Routes>
</BrowserRouter>

React Router with Module Federation

Each MFE can run its own React Router, scoped to its basepath. The host router handles top-level navigation; each remote handles sub-navigation independently.

// Remote App component:
export function ProductsApp({ basepath = '/products' }) {
  return (
    <BrowserRouter basename={basepath}>
      <Routes>
        <Route path="/" element={<ProductList />} />
        <Route path="/:id" element={<ProductDetail />} />
      </Routes>
    </BrowserRouter>
  );
}

Shared Auth State

Auth state (user, token) is typically owned by the shell and passed down to remotes as props or exposed via a shared singleton store.

// Host provides auth via props:
<RemoteCheckout
  userId={currentUser.id}
  token={accessToken}
  onLogout={handleLogout}
/>

Zustand as Shared Store

When sharing a Zustand store via Module Federation (as a singleton), all MFEs read from the same store instance in memory.

// shared/store.ts (exposed as singleton)
import { create } from 'zustand';
export const useCartStore = create(set => ({
  items: [],
  addItem: (item) => set(state => ({ items: [...state.items, item] })),
}));

// Configured as singleton in MF shared config

Cross-MFE Communication Anti-Patterns

Avoid: deeply nested callback chains, sharing internal component state, or tight coupling to another MFE's internal APIs. Keep communication to coarse events and public contracts.

Testing Cross-MFE Interactions

Test the event contracts (event names, data shapes) separately from the UI. Use contract testing to verify that producer and consumer agree on the event schema.

Quick Check

What is the simplest way to share navigation/filter state between multiple micro-frontends without coupling them?

Recap

Share state between MFEs via custom events, a singleton event bus, the URL, or shared stores (Zustand/singleton). The shell owns the top-level router and passes basepath + navigate to remotes. Keep cross-MFE contracts coarse and well-typed.

Frequently asked questions

Is the “Shared State & Routing Between MFEs” lesson free?

Yes — the full text of “Shared State & Routing Between MFEs” is free to read here on the web, and the React Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the React Academy course, upgrade to CoddyKit PRO.

What will I learn in “Shared State & Routing Between MFEs”?

Share a global event bus or context across micro-frontends and coordinate client-side routing. You practise React Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start React Academy?

No prior experience is required. React Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Shared State & Routing Between MFEs” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this React Academy lesson?

Yes. Every React Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Micro-Frontend Concepts & Trade-offs
  2. Module Federation with Webpack 5
  3. Shared State & Routing Between MFEs
  4. Independent Deployment & CI Pipelines for MFEs
← Back to React Academy