{"id":12035,"library":"single-spa-react","title":"single-spa-react","description":"single-spa-react is a utility library designed to simplify the integration of React applications and components into a single-spa microfrontend architecture. It provides helper functions that adapt React's rendering and lifecycle methods (bootstrap, mount, unmount) to single-spa's expectations. The current stable version is 6.0.2, with ongoing active development including patch releases and a v7.0.0-beta.0 in progress. Key differentiators include robust support for React 18's `createRoot` API, explicit compatibility options for older React versions, built-in error boundary mechanisms, and a dedicated `<Parcel>` component for managing framework-agnostic micro-frontends within a React application. It focuses on ensuring React applications adhere to single-spa's lifecycle contracts and work seamlessly within a polyglot microfrontend environment.","status":"active","version":"6.0.2","language":"javascript","source_language":"en","source_url":"https://github.com/joeldenning/single-spa-react","tags":["javascript","single","page","application","spa","react","typescript"],"install":[{"cmd":"npm install single-spa-react","lang":"bash","label":"npm"},{"cmd":"yarn add single-spa-react","lang":"bash","label":"yarn"},{"cmd":"pnpm add single-spa-react","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core React library required by the application being wrapped.","package":"react","optional":false},{"reason":"TypeScript type definitions for React, required for TypeScript projects.","package":"@types/react","optional":true},{"reason":"TypeScript type definitions for ReactDOM, required for TypeScript projects.","package":"@types/react-dom","optional":true}],"imports":[{"note":"This is the primary default export for configuring React application lifecycles. Ensure you are using ESM imports in modern setups.","wrong":"const singleSpaReact = require('single-spa-react').default;","symbol":"singleSpaReact","correct":"import singleSpaReact from 'single-spa-react';"},{"note":"Provides a React Context to access single-spa props within your components, useful for inter-app communication. It's a named export from the main package.","wrong":"import SingleSpaContext from 'single-spa-react/SingleSpaContext';","symbol":"SingleSpaContext","correct":"import { SingleSpaContext } from 'single-spa-react';"},{"note":"The `<Parcel>` component is used to embed single-spa parcels directly into a React component's render method, simplifying parcel management. It is imported from a subpath.","wrong":"import { Parcel } from 'single-spa-react';","symbol":"Parcel","correct":"import Parcel from 'single-spa-react/parcel';"}],"quickstart":{"code":"import React from 'react';\nimport ReactDOMClient from 'react-dom/client'; // For React 18+\nimport singleSpaReact from 'single-spa-react';\n\n// A simple React component for the microfrontend\nconst MyReactApp = ({ name, mountParcel }) => {\n  const [count, setCount] = React.useState(0);\n\n  React.useEffect(() => {\n    console.log(`${name} mounted!`);\n    return () => console.log(`${name} unmounted!`);\n  }, [name]);\n\n  return (\n    <div style={{\n      padding: '20px',\n      border: '1px solid #61dafb',\n      borderRadius: '8px',\n      margin: '10px',\n      backgroundColor: '#282c34',\n      color: 'white'\n    }}>\n      <h2>Hello from {name}!</h2>\n      <p>Count: {count}</p>\n      <button onClick={() => setCount(c => c + 1)} style={{ padding: '8px 16px', borderRadius: '4px', cursor: 'pointer' }}>Increment</button>\n      <p>This is a single-spa React application.</p>\n      {/* Optionally mount a parcel here */}\n      {/* <Parcel config={mountParcel} wrapWith='div' /> */}\n    </div>\n  );\n};\n\n// A basic error boundary component is highly recommended for robustness.\nclass ErrorBoundary extends React.Component {\n  state = { hasError: false };\n  static getDerivedStateFromError(error) { return { hasError: true }; }\n  componentDidCatch(error, errorInfo) {\n    console.error(\"React component error:\", error, errorInfo);\n  }\n  render() {\n    if (this.state.hasError) {\n      return <h1 style={{ color: 'red' }}>Something went wrong in {this.props.name}.</h1>;\n    }\n    return this.props.children;\n  }\n}\n\n// Configure single-spa-react with your React application.\nconst lifecycles = singleSpaReact({\n  React, // Pass the React library\n  ReactDOMClient, // Use ReactDOMClient for React 18+ for createRoot. For React 17-, use ReactDOM and specify renderType: 'render'.\n  rootComponent: MyReactApp, // Your top-level React component\n  // A function that returns the DOM element where the React app will be mounted.\n  domElementGetter: () => {\n    let el = document.getElementById('react-app-container');\n    if (!el) {\n      el = document.createElement('div');\n      el.id = 'react-app-container';\n      document.body.appendChild(el); // Append to body or a specific parent defined in your root config\n    }\n    return el;\n  },\n  // Recommended: Provide an error boundary for better fault tolerance.\n  errorBoundary: ErrorBoundary,\n  // Optional: Pass custom props to your root component.\n  getAppProps: ({ name, ...props }) => ({ name: name || 'Default React App', ...props }),\n  // Suppress warning if using an errorBoundary function/class\n  suppressComponentDidCatchWarning: true\n});\n\n// Export single-spa lifecycles for your microfrontend.\nexport const { bootstrap, mount, unmount } = lifecycles;\n","lang":"typescript","description":"This quickstart demonstrates how to wrap a React application for single-spa using `single-spa-react`. It showcases React 18's `ReactDOMClient`, integrates an error boundary, and defines the `domElementGetter` for mounting."},"warnings":[{"fix":"For React 18+, replace `ReactDOM` with `ReactDOMClient` (e.g., `import ReactDOMClient from 'react-dom/client';`) and pass `ReactDOMClient` to `singleSpaReact`. For React 17 or older, you must explicitly set the `renderType` option to `'render'` in your `singleSpaReact` configuration (e.g., `singleSpaReact({ ..., renderType: 'render' })`).","message":"Upgrading to `single-spa-react` v5.0.0 or higher, particularly when targeting React 18, requires significant changes to ReactDOM usage. The default `renderType` switched from `render` to `createRoot` to align with React 18's new concurrent rendering API.","severity":"breaking","affected_versions":">=5.0.0"},{"fix":"Ensure your bundler (e.g., Webpack, Rollup) and TypeScript configuration are up-to-date and using standard module resolution settings. Review your import statements for `single-spa-react` and its subpaths to ensure they align with standard ESM resolution. You might need to adjust `tsconfig.json`'s `moduleResolution` if experiencing import errors.","message":"Version 6.0.0 introduced 'Enhanced compatibility with various bundlers and TypeScript `moduleResolution` strategies,' along with refined package export patterns. This change, while improving modern tooling integration, may cause issues with older or non-standard bundler configurations or TypeScript setups that relied on specific internal module paths.","severity":"breaking","affected_versions":">=6.0.0"},{"fix":"Provide an `errorBoundary` function or an `errorBoundaryClass` in your `singleSpaReact` options, or ensure your root component itself implements `componentDidCatch`. Setting `suppressComponentDidCatchWarning: true` can silence the warning if you're handling errors externally.","message":"For React applications (>=16) integrated with single-spa, it is considered best practice to implement `componentDidCatch` (or an equivalent functional error boundary) in your root component. Failure to do so will result in console warnings from `single-spa-react` and could lead to the entire application unmounting unexpectedly on an unhandled error.","severity":"gotcha","affected_versions":">=4.0.0"},{"fix":"If IE11 support is critical, consider pinning to an older, compatible version of `single-spa-react` and `single-spa` (e.g., `single-spa-react@4.x` and `single-spa@5.x`). Otherwise, plan to migrate users to modern browsers. Always consult the specific `single-spa` and `single-spa-react` changelogs for precise IE11 compatibility statements.","message":"Internet Explorer 11 (IE11) support has been deprecated or removed in `single-spa` core v6.0.0, and `single-spa-react` may follow a similar trajectory. Using recent versions with IE11 may lead to compatibility issues.","severity":"gotcha","affected_versions":">=6.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Update your `singleSpaReact` configuration to use `ReactDOMClient` from `react-dom/client` (for React 18+) and remove any explicit `renderType: 'render'` if you are on React 18. If intentionally using React 17 or below, explicitly set `renderType: 'render'`.","cause":"Attempting to use `ReactDOM.render` with React 18 in `single-spa-react` after the default rendering mechanism changed to `createRoot`.","error":"TypeError: ReactDOM.render is not a function"},{"fix":"Ensure your `domElementGetter` function correctly selects or creates a valid DOM element in the document. Verify the element ID or class name, and ensure the element exists by the time `mount` is called. Remember that `domElementGetter` is not required when creating a single-spa parcel.","cause":"The `domElementGetter` function provided to `singleSpaReact` is returning `null` or an invalid DOM element, preventing React from mounting.","error":"Error: Target container is not a DOM element."},{"fix":"Configure your application's bundler (e.g., Webpack `externals`) to treat `react` and `react-dom` as external dependencies. Ensure your `single-spa` root configuration's import map correctly defines the URLs for the shared `react` and `react-dom` libraries.","cause":"This typically occurs in single-spa setups using SystemJS and import maps where the `react` (or `react-dom`) dependency is not correctly externalized in the application's build or is missing from the root config's import map.","error":"Unable to resolve bare specifier 'react' from <your-app-bundle.js>"}],"ecosystem":"npm"}