{"id":15415834,"url":"https://github.com/davidje13/react-portal-target","last_synced_at":"2026-05-08T10:36:38.726Z","repository":{"id":57714435,"uuid":"517086223","full_name":"davidje13/react-portal-target","owner":"davidje13","description":"Allows rendering components elsewhere in the React tree","archived":false,"fork":false,"pushed_at":"2022-07-24T21:40:40.000Z","size":18,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-09-24T03:26:40.737Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/davidje13.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-07-23T14:55:08.000Z","updated_at":"2022-07-23T15:00:33.000Z","dependencies_parsed_at":"2022-09-26T21:31:25.729Z","dependency_job_id":null,"html_url":"https://github.com/davidje13/react-portal-target","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/davidje13/react-portal-target","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2Freact-portal-target","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2Freact-portal-target/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2Freact-portal-target/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2Freact-portal-target/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/davidje13","download_url":"https://codeload.github.com/davidje13/react-portal-target/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2Freact-portal-target/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32776962,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-08T08:22:46.396Z","status":"ssl_error","status_checked_at":"2026-05-08T08:22:45.650Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-01T17:09:55.035Z","updated_at":"2026-05-08T10:36:38.689Z","avatar_url":"https://github.com/davidje13.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# React Portal Target\n\nAllows React components to put content elsewhere on the page, for example pages\ndefining content to show in a shared header or footer.\n\nLike [React Portal](https://reactjs.org/docs/portals.html), but the target is\nanother location in the React component tree (or a hook) instead of targeting\na DOM node.\n\n## Example\n\n```shell\nnpm install --save react-portal-target\n```\n\n### Components API\n\n```jsx\nconst MyHeader = () =\u003e (\n  \u003cheader\u003eWelcome. \u003cPortalTarget name=\"mytarget\" /\u003e\u003c/header\u003e\n);\n\nconst MyPage = () =\u003e (\n  \u003cmain\u003e\n    This is a page\n    \u003cPortalSource name=\"mytarget\"\u003e\n      You're looking at page \u003cstrong\u003eone\u003c/strong\u003e\n    \u003c/PortalSource\u003e\n  \u003c/main\u003e\n);\n\nReactDOM.render((\n  \u003cPortalContext\u003e\n    \u003cMyHeader /\u003e\n    \u003cMyPage /\u003e\n  \u003c/PortalContext\u003e\n), document.body);\n```\n\nRenders as:\n\n```html\n\u003cheader\u003eWelcome. You're looking at page \u003cstrong\u003eone\u003c/strong\u003e\u003c/header\u003e\n\u003cmain\u003eThis is a page\u003c/main\u003e\n```\n\n### Hooks API\n\nNote that the components API simply wraps the hooks, and is recommended in most\ncases. But if you need to be able to perform additional processing, you can use\nthe hooks directly (it is also possible to mix-and-match the hooks and\ncomponents APIs, for example using a hook target and a component source).\n\n```jsx\nconst MyHeader = () =\u003e {\n  const content = usePortalTarget('mytarget');\n  if (!content) {\n    return (\u003cheader\u003eNo page active!\u003c/header\u003e);\n  }\n  return (\u003cheader\u003eWelcome. {content}\u003c/header\u003e);\n};\n\nconst MyPage = () =\u003e {\n  usePortalSource(\n    'mytarget',\n    \u003c\u003eYou're looking at page \u003cstrong\u003eone\u003c/strong\u003e\u003c/\u003e\n  );\n  return (\u003cmain\u003eThis is a page\u003c/main\u003e);\n};\n\nReactDOM.render((\n  \u003cPortalContext\u003e\n    \u003cMyHeader /\u003e\n    \u003cMyPage /\u003e\n  \u003c/PortalContext\u003e\n), document.body);\n```\n\nRenders as:\n\n```html\n\u003cheader\u003eWelcome. You're looking at page \u003cstrong\u003eone\u003c/strong\u003e\u003c/header\u003e\n\u003cmain\u003eThis is a page\u003c/main\u003e\n```\n\n## API\n\n### `\u003cPortalContext\u003e`\n\n```xml\n\u003cPortalContext\u003e...\u003c/PortalContext\u003e\n```\n\nProvides the context for passing data between components. This should be high\nup in your component tree so that it contains all sources and targets.\n\nIf not used, a global context is used by default.\n\n\n### `\u003cPortalTarget\u003e`\n\n```xml\n\u003cPortalTarget name=\"my-target-name\" /\u003e\n\u003cPortalTarget name=\"my-target-name\"\u003edefault content\u003c/PortalTarget\u003e\n```\n\nDefines an outlet for displaying content. You can optionally specify default\ncontent to display when no sources are linked to the target.\n\nThe content will be wrapped in a React Fragment.\n\nIf multiple targets are defined with the same name, the content will only be\nshown in the first target to render (once that target unmounts, it will move to\nthe second, and so on.)\n\nSee also [`usePortalTarget`](#useportaltarget).\n\n\n### `usePortalTarget`\n\n```jsx\ncontent = usePortalTarget(name)\ncontent = usePortalTarget(name, defaultContent)\n```\n\nDefines an outlet for displaying content, returning the current content. You\ncan optionally specify default content to return when no sources are linked to\nthe target.\n\nThe content is returned exactly as it was provided, with no processing or\nwrapping.\n\nSee also [`PortalTarget`](#portaltarget).\n\n\n### `\u003cPortalSource\u003e`\n\n```xml\n\u003cPortalSource name=\"my-target-name\"\u003econtent\u003c/PortalSource\u003e\n```\n\nDefines an inlet for providing content.\n\nIf multiple sources are defined for the same target, only one will be displayed\nat a time (the first to render, though this may not always be the first on the\npage).\n\nSee also [`usePortalSource`](#useportalsource).\n\n\n### `usePortalSource`\n\n```jsx\nusePortalSource(name, content)\n```\n\nDefines an inlet for providing content. The content should be one of:\n\n* a string,\n* an element,\n* null\n* an array of the above\n\nThe recommended way to provide multi-element content is to wrap it in a fragment:\n\n```jsx\nusePortalSource('my-thing', \u003c\u003efoo\u003cstrong\u003ebar\u003c/strong\u003e\u003c/\u003e);\n```\n\nbut it is also possible to provide it as an array:\n\n```jsx\nusePortalSource('my-thing', ['foo', \u003cstrong\u003ebar\u003c/strong\u003e]);\n```\n\nSee also [`PortalSource`](#portalsource).\n\n\n## Caveats\n\nBecause this internally relies on `useLayoutEffect`, it will not render as part\nof server-side-rendering (the portaled content will be unavailable until the\ntree is hydrated on the client). If server-side-rendering is important to you,\nyou will need to re-structure your page to put the portaled content directly\ninside the target element.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidje13%2Freact-portal-target","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavidje13%2Freact-portal-target","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidje13%2Freact-portal-target/lists"}