# Layouts With React Plugin layouts are real React components. They can use JSX and hooks. ```tsx import type { PluginLayoutProps } from "@idea/plugin-sdk"; import { useState } from "react"; export function Dashboard(props: PluginLayoutProps): React.ReactElement { const [localClicks, setLocalClicks] = useState(0); return ( ); } ``` Register the component for a manifest-declared layout type: ```ts ctx.layouts?.register({ type: "hello-plugin.dashboard", component: Dashboard }); ``` ## Props - `projectId`: project hosting the layout. - `nodeId`: stable host node id for this layout instance. - `layoutType`: manifest layout `type`. - `state`: JSON-serializable host-persisted state. - `setState(next)`: replace host-persisted state. - `availability`: currently `"available"` while mounted. Call `setState` from user actions, effects or async callbacks. Do not call it unconditionally during render. ## Host React Plugins must import React normally: ```ts import { useEffect, useMemo, useState } from "react"; ``` At runtime IdeA resolves these bare imports to the host instance: - `react` - `react-dom` - `react-dom/client` - `react/jsx-runtime` - `react/jsx-dev-runtime` Do not bundle your own copy of React or ReactDOM into the plugin. Declare them as `peerDependencies` and `devDependencies` for local typechecking/builds. ```json { "peerDependencies": { "react": "^18.2.0 || ^19.0.0", "react-dom": "^18.2.0 || ^19.0.0" }, "devDependencies": { "@types/react": "^19.0.0", "@types/react-dom": "^19.0.0", "react": "^19.0.0", "react-dom": "^19.0.0" } } ``` ## Build Use `jsx: "react-jsx"` in `tsconfig`. A plain multi-file ESM `tsc` build is supported as long as every emitted file imported by `main` is included in the archive.