Gathering detailed insights and metrics for @leanjs/react
Gathering detailed insights and metrics for @leanjs/react
Gathering detailed insights and metrics for @leanjs/react
Gathering detailed insights and metrics for @leanjs/react
npm install @leanjs/react
Typescript
Module System
Node Version
NPM Version
@leanjs/vue-router@0.7.8
Updated on Dec 31, 2022
@leanjs/webpack@0.21.8
Updated on Dec 18, 2022
@leanjs/webpack-vue@0.4.2
Updated on Dec 18, 2022
@leanjs/website@0.1.3
Updated on Dec 18, 2022
@leanjs/cli@0.7.38
Updated on Dec 18, 2022
@leanjs/next@0.8.12
Updated on Dec 18, 2022
TypeScript (79.84%)
JavaScript (14.19%)
Vue (2.14%)
Perl (1.62%)
Raku (1.33%)
CSS (0.52%)
HTML (0.33%)
Shell (0.03%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MIT License
170 Stars
949 Commits
6 Forks
4 Watchers
14 Branches
9 Contributors
Updated on May 28, 2025
Latest Version
0.20.3
Package Id
@leanjs/react@0.20.3
Unpacked Size
47.56 kB
Size
10.97 kB
File Count
35
NPM Version
lerna/5.6.2/node@v16.19.0+x64 (linux)
Node Version
16.19.0
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
If your React app is in a monorepo (recommended) execute the following command at the root of your repository:
1yarn add -W @leanjs/react @leanjs/core react react-dom
then in the package.json
of your React app add the following peerDependencies
:
"peerDependencies": {
"@leanjs/core": "*",
"@leanjs/react": "*",
"react": "*",
"react-dom": "*"
}
If your React app is not in a monorepo, then run the following command instead of the above:
1yarn add @leanjs/react @leanjs/core react react-dom
createRuntimeBindings
First, you have to create your React bindings (HostProvider, useGetter, etc) for your runtime
.
1// shared-runtime.ts 2 3// for either React 16 or React 17 import from "@leanjs/react/17" 4import { createRuntimeBindings } from "@leanjs/react/18"; 5import { configureRuntime } from "@leanjs/core"; 6 7// You need to configure your runtime 8const defaultState = { locale: "en" }; // this is just an example 9export const { createRuntime } = configureRuntime(defaultState)({ 10 onError: () => {}, 11}); 12 13// Then create your React bindings for your runtime 14export const { 15 HostProvider, 16 useGetter, 17 useSetter, 18 useLoading, 19 useError, 20 useRuntime, 21} = createRuntimeBindings(createRuntime);
:::info
Read @leanjs/core if you have not already created your own createRuntime
function
:::
Add your HostProvider
at the root of your React component tree, e.g.
1// It's recommended to move your ./shared-runtime file to its own package 2import { createRuntime, HostProvider } from "./shared-runtime"; 3 4const runtime = createRuntime({ context: { appName: "AppExample" } }); 5 6export function App({ children }) { 7 return <HostProvider runtime={runtime}>{children}</HostProvider>; 8}
Use any of your hooks in your components, e.g.
1// It's recommended to move your ./shared-runtime file to its own package 2import { useGetter } from "./shared-runtime"; 3 4export function LocaleComponent() { 5 const locale = useGetter("locale"); 6 7 return <p>Current locale is {locale}</p>; 8}
Create small React apps that can be composed with other apps.
createApp
Arguments:
App: ReactElement
- requiredoptions: { appName?: string }
- optional. By default, the name of your composable app is the name of your App
component. You can change it using the optional argument appName
.Create a file called index.ts|js
in the src
directory where your composable app is. For example:
my-monorepo/
├─ apps/
│ ├─ react-host/
├─ composable-apps/
│ ├─ react-app-1/
│ │ ├─ package.json
│ │ ├─ src/
│ │ │ ├─ ReactApp1.tsx
│ │ │ ├─ index.ts 👈
├─ package.json
:::tip
Read the recommended setup in our getting started page if you want to create a similar monorepo structure
:::
Call createApp
with the root component of your app, for example:
1// my-monorepo/composable-apps/react-app-1/src/index.ts 2 3// for either React 16 or React 17 import from "@leanjs/react/17" 4import { createApp } from "@leanjs/react/18"; 5 6import { ReactApp1 } from "./ReactApp1"; 7 8// 👇 you have to `export default` 9export default createApp(ReactApp1); 10 11// The name of the composable app is the name of your component, 12// "ReactApp1 in this case. 13// you can name it differently using the second argument, e.g. 14// export default createApp(ReactApp1, { appName: "SomeName" });
Hello world example of the ReactApp1
imported above
1// my-monorepo/composable-apps/react-app-1/src/ReactApp1.tsx 2 3import React from "react"; 4 5export const ReactApp1 = () => <h1>Hello React composable app 1</h1>;
Create a file called selfHosted.ts|js
in the src
directory where your composable app is, for example:
my-monorepo/
├─ apps/
│ ├─ react-host/
├─ composable-apps/
│ ├─ react-app-1/
│ │ ├─ package.json
│ │ ├─ src/
│ │ │ ├─ ReactApp1.tsx
│ │ │ ├─ index.ts
│ │ │ ├─ selfHosted.ts 👈
├─ package.json
Export a createRuntime
function from the selfHosted.ts|js
file. This is the runtime that will be used when the app runs in isolation, meaning without a host.
1// my-monorepo/composable-apps/react-app-1/src/selfHosted.ts 2 3export { createRuntime } from "@my-org/runtime-react";
:::info
Read @leanjs/core if you have not already created your own createRuntime
function
:::
HostProvider
You have to call createRuntimeBindings to create a HostProvider
component before you use it. HostProvider
stores in a React context values that are shared across apps hosted in the same component tree. Props:
runtime
prop - requiredYour Lean runtime.
origin
prop - optionalOrigin where your remote composable apps are. During development, use the address where you run your Lean proxy dev server. Use the address of your CDN in production, e.g. https://cdn.example.com
.
Example
1// where does shared-runtime come from? Read the "Usage" section at the top 2import { createRuntime, HostProvider } from "./shared-runtime"; 3 4const runtime = createRuntime({ context: { appName: "AppExample" } }); 5// origin is optional, it's only used if micro-frontends are enabled 6const origin = process.env.MICROFRONTENDS_ORIGIN; 7 8export function App({ children }) { 9 return ( 10 <HostProvider runtime={runtime} origin={origin}> 11 {children} 12 </HostProvider> 13 ); 14}
It catches both rendering errors and errors from Suspense.
children
- required propReact nodes displayed if there are no errors.
fallback
- optional propError fallback component displayed when an error is caught by the ErrorBoundary
.
1type ErrorFallbackComponent = (props: { 2 error: AppError; 3}) => React.ReactElement; 4 5interface AppError extends Error { 6 appName?: string; 7 version?: string; 8}
onError
- optional propFunction called when an error is caught.
1onError?: (error: AppError, options?: LogErrorOptions) => void; 2 3interface LogErrorOptions { 4 appName?: string; 5 version?: string; 6} 7 8interface AppError extends Error, LogErrorOptions {}
If onError
is not provided and an error is caught by the ErrorBoundary
the error will be logged using the onError
function passed to the configureRuntime
if a HostProvider
is found in the component tree.
Host
It hosts a composable app in a React host.
app
- required propThe app
prop expects a GetComposableApp
type. You can import
a GetComposableApp
from any export default createApp()
function, for instance:
1// my-monorepo/composable-apps/react-app-1/src/index.tsx 2 3// for either React 16 or React 17 import from "@leanjs/react/17" 4import { createApp } from "@leanjs/react/18"; 5import { ReactApp1 } from "./ReactApp1"; 6 7export default createApp(ReactApp1);
then pass it to the Host
component in a React app:
1// my-monorepo/apps/react-host/src/index.ts 2 3import React from "react"; 4// for either React 16 or React 17 import from "@leanjs/react/17" 5import { Host } from "@leanjs/react/18"; 6 7// this composable app is bundled and deployed along with the host app 8import ReactApp1 from "@my-org/react-app-1"; 9 10const Home = () => ( 11 <> 12 <h1>React Host</h1> 13 <Host app={ReactApp1} /> 14 </> 15); 16 17export default Home;
:::info
In this example, both the host app and the composable app are React apps. However, the React <Host>
component can host any composable app, e.g. Vue.
:::
You can also pass a function to the Host
component that returns a dynamic import to lazy load a composable app:
1// my-monorepo/apps/react-host/src/index.ts 2 3import React, { Suspense } from "react"; 4// for either React 16 or React 17 import from "@leanjs/react/17" 5import { Host, ErrorBoundary } from "@leanjs/react/18"; 6 7const Home = () => ( 8 <> 9 <h1>React Host</h1> 10 {/* The network can fail. 11 Add an ErrorBoundary if you are hosting an app using a dynamic import */} 12 <ErrorBoundary> 13 <Suspense fallback={<p>Loading...</p>}> 14 <Host 15 app={() => { 16 // this composable app is bundled in a separate chunk 17 // but it's still built and deployed along with the host app 18 return import("@my-org/react-app-1"); 19 }} 20 /> 21 </Suspense> 22 </ErrorBoundary> 23 </> 24); 25 26export default Home;
Alternatively, you can pass an object to the app
prop with a packageName
key which value is the field name
in the package.json of the composable app that you want to host. In this case, the Host
component will try to fetch the mount
function from the remote origin
specified in <HostProvider origin=" 👉 HERE 👈 " runtime={runtime}>
(see origin prop to know more). For example:
1// my-monorepo/apps/react-host/src/index.ts 2 3// for either React 16 or React 17 import from "@leanjs/react/17" 4import { Host, ErrorBoundary } from "@leanjs/react/18"; 5 6const Home = () => ( 7 <> 8 <h1>React Host</h1> 9 {/* The network can fail. 10 Add an ErrorBoundary if you are hosting a remote app */} 11 <ErrorBoundary> 12 <Suspense fallback={<p>Loading...</p>}> 13 {/* in this case, the composable app is neither built nor deployed 14 along with the React host */} 15 <Host app={{ packageName: "@my-org/react-app-1" }} /> 16 </Suspense> 17 </ErrorBoundary> 18 </> 19); 20 21export default Home;
:::caution
Fetching from a remote origin
only works with Webpack v5 because this feature uses Module Federation under the hood. You need to add a HostWebpackPlugin to your Webpack configuration to enable this feature. If this feature is enabled you need to build and deploy your composable apps independently. See @leanjs/aws to deploy your composable apps to AWS.
:::
:::tip
You can still pass an import
(either dynamic or static) to the app
prop of the Host
component and configure Webpack to fetch it from a remote origin by changing the configuration of your HostWebpackPlugin
.
:::
Tip example:
1// webpack.config.js of the host application 2const { HostWebpackPlugin } = require("@leanjs/webpack"); 3 4module.exports = { 5 // the rest of your configuration goes here 6 plugins: [ 7 new HostWebpackPlugin({ 8 remotes: { 9 // these packages are not built along with the host app 10 // but downloaded from a remote origin 11 packages: ["@my-org/react-app-1"], 12 }, 13 }), 14 ], 15};
then in your React app:
1// my-monorepo/apps/react-host/src/index.ts 2 3import React, { Suspense } from "react"; 4// for either React 16 or React 17 import from "@leanjs/react/17" 5import { Host, ErrorBoundary } from "@leanjs/react/18"; 6 7// this composable app is neither bundled nor deployed along with the host app 8// because of the above remote: { packages: ["@my-org/react-app-1"] } 9// in the webpack.config.js HostWebpackPlugin 10import ReactApp1 from "@my-org/react-app-1"; 11 12const Home = () => ( 13 <> 14 <h1>React Host</h1> 15 {/* The network can fail. 16 Add an ErrorBoundary if you are hosting a remote app */} 17 <ErrorBoundary> 18 <Suspense fallback={<p>Loading...</p>}> 19 <Host app={ReactApp1} /> 20 </Suspense> 21 </ErrorBoundary> 22 </> 23); 24 25export default Home;
Pro-tip
Configure your remotes
in HostWebpackPlugin
on development only. This way no CI/CD changes are required. It also reduces build time of your monolith in development since these packages are excluded from the monolith build. Last but not least, you can experiment with micro-frontends in development without changing how you implement and host your apps.
Pro-tip example:
1// webpack.config.js of the host application 2const { HostWebpackPlugin } = require("@leanjs/webpack"); 3 4module.exports = { 5 // the rest of your configuration goes here 6 plugins: [ 7 new HostWebpackPlugin({ 8 remotes: { 9 // the following packages are built and deployed along with 10 // the React app on production, but not during development. 11 packages: 12 process.env.NODE_ENV === "production" ? [] : ["@my-org/react-app-1"], 13 }, 14 }), 15 ], 16};
className
- optional propCSS class added to the root DOM element where the app
prop is mounted.
1// my-monorepo/apps/react-host/src/index.ts 2 3import React from "react"; 4// for either React 16 or React 17 import from "@leanjs/react/17" 5import { Host } from "@leanjs/react/18"; 6import ReactApp1 from "@my-org/react-app-1"; 7 8const Home = () => ( 9 <> 10 <h1>React Host</h1> 11 <Host className="some-css-class" app={ReactApp1} /> 12 </> 13); 14 15export default Home;
useGetter
Hook to get the current state of a given state property. You have to call createRuntimeBindings to create a useGetter
hook before you use it.
Arguments:
The output is the current state of the given property.
Example:
1// where does shared-runtime come from? Read the "Usage" section at the top 2import { useGetter } from "./shared-runtime"; 3 4export function LocaleComponent() { 5 const locale = useGetter("locale", () => 6 fetch("/api/settings") 7 .then((response) => response.json()) 8 .then((data) => data.locale) 9 ); 10 11 return <p>Locale is {locale}</p>; 12}
useSetter
Hook to update the value of a given state property. You have to call createRuntimeBindings to create a useSetter
hook before you use it.
Arguments:
The output is a function to update the value of the given state property.
Example:
1// where does shared-runtime come from? Read the "Usage" section at the top 2import { useSetter } from "./shared-runtime"; 3 4export function ThemeSelector() { 5 const setTheme = useSetter("theme"); 6 7 return ( 8 <> 9 <label for="theme-select">Choose a theme:</label> 10 <select 11 onChange={(e) => setTheme(e.target.value)} 12 name="theme" 13 id="theme-select" 14 > 15 <option value="">--Please choose an option--</option> 16 <option value="dark">Dark</option> 17 <option value="light">Light</option> 18 </select> 19 </> 20 ); 21}
useLoading
Hook to get the loading state of a given state property. You have to call createRuntimeBindings to create a useLoading
hook before you use it.
Arguments:
The output is a boolean indicating if the given state property is loading.
Example:
1// where does shared-runtime come from? Read the "Usage" section at the top 2import { useLoading } from "./shared-runtime"; 3 4export function LocaleSpinner() { 5 const loading = useLoading("locale"); 6 7 if (loading) { 8 return <p>Loading...</p>; 9 } else { 10 return null; 11 } 12}
useError
Hook to get the error state if a given state property failed to load. You have to call createRuntimeBindings to create a useError
hook before you use it.
Arguments:
The output is undefined or a string with the error message.
Example:
1// where does shared-runtime come from? Read the "Usage" section at the top 2import { useError } from "./shared-runtime"; 3 4export function LocaleErrorMessage() { 5 const error = useError("locale"); 6 7 if (error) { 8 return <p>Oops, locale error: {error} </p>; 9 } else { 10 return null; 11 } 12}
useRuntime
It returns the shared runtime
from the context. You have to call createRuntimeBindings to create a useRuntime
hook before you use it.
Example:
1// where does shared-runtime come from? Read the "Usage" section at the top 2import { useRuntime } from "./shared-runtime"; 3 4// HostProvider must be an ancestor of the following component 5export function Component() { 6 const runtime = useRuntime(); // do something with runtime 7 8 return <h1>My component</h1>; 9}
No vulnerabilities found.
Reason
no dangerous workflow patterns detected
Reason
no binaries found in the repo
Reason
license file detected
Details
Reason
Found 3/6 approved changesets -- score normalized to 5
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
security policy file not detected
Details
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
Reason
project is not fuzzed
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Reason
87 existing vulnerabilities detected
Details
Score
Last Scanned on 2025-07-07
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More