{"id":24775973,"url":"https://github.com/ivliu/react-offscreen","last_synced_at":"2025-04-13T00:41:32.241Z","repository":{"id":156168148,"uuid":"632880550","full_name":"IVLIU/react-offscreen","owner":"IVLIU","description":"react offscreen component like vue keep-alive","archived":false,"fork":false,"pushed_at":"2025-03-15T13:44:24.000Z","size":16482,"stargazers_count":136,"open_issues_count":4,"forks_count":10,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-04T07:16:53.949Z","etag":null,"topics":["keep-alive","offscreen","react","react-offscreen"],"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/IVLIU.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-04-26T10:16:06.000Z","updated_at":"2025-03-23T12:43:35.000Z","dependencies_parsed_at":"2025-01-20T06:22:32.459Z","dependency_job_id":"0d40cb0d-5841-437a-8661-41fe879d6e73","html_url":"https://github.com/IVLIU/react-offscreen","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IVLIU%2Freact-offscreen","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IVLIU%2Freact-offscreen/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IVLIU%2Freact-offscreen/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IVLIU%2Freact-offscreen/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/IVLIU","download_url":"https://codeload.github.com/IVLIU/react-offscreen/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248650414,"owners_count":21139672,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["keep-alive","offscreen","react","react-offscreen"],"created_at":"2025-01-29T06:56:26.121Z","updated_at":"2025-04-13T00:41:32.206Z","avatar_url":"https://github.com/IVLIU.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# react-offscreen(activity)\n\n![NPM Version](https://img.shields.io/npm/v/%40ivliu%2Freact-offscreen)\n![License](https://img.shields.io/badge/license-MIT-yellow)\n\nreact-offscreen can hide components without uninstalling them\n\n## Features\n\n- based on Suspense\n- minzip only 1.2kb\n- good performance\n- react full context support\n\n## Installation\n\n```bash\nnpm install @ivliu/react-offscreen\nyarn add @ivliu/react-offscreen\npnpm add @ivliu/react-offscreen\n```\n\n## Examples\n\n### Basic usage\n\n```typescript\nimport { useState } from 'react';\nimport ReactDOM from 'react-dom/client';\nimport { Activity } from '@ivliu/react-offscreen';\n\nconst Counter = () =\u003e {\n  const [count, setCount] = useState(0);\n\n  return \u003cp onClick={() =\u003e setCount(count + 1)}\u003e{count}\u003c/p\u003e;\n};\n\nconst App = () =\u003e {\n  const [open, setOpen] = useState(false);\n\n  return (\n    \u003cdiv\u003e\n      \u003cbutton onClick={() =\u003e setVisible(!open)}\u003e{open}\u003c/button\u003e\n      \u003cActivity mode={open ? 'visible' : 'hidden'}\u003e\n        \u003cCounter /\u003e\n      \u003c/Activity\u003e\n    \u003c/div\u003e\n  );\n};\n\nReactDOM.createRoot(document.getElementById('root')!).render(\u003cApp /\u003e);\n```\n\n### Use with createPortal\n\n```typescript\nimport { useState } from 'react';\nimport ReactDOM from 'react-dom/client';\nimport { createPortal } from 'react-dom';\nimport { Activity } from '@ivliu/react-offscreen';\n\nconst Counter = () =\u003e {\n  const [count, setCount] = useState(0);\n\n  return createPortal(\n    \u003cbutton type=\"button\" onClick={() =\u003e setCount(count + 1)}\u003ecount is {count}\u003c/button\u003e,\n    document.body,\n  );\n};\n\nconst App = () =\u003e {\n  const [open, setOpen] = useState(false);\n  return (\n    \u003cdiv\u003e\n      \u003cbutton onClick={() =\u003e setVisible(!open)}\u003e{open}\u003c/button\u003e\n      \u003cActivity mode={open ? 'visible' : 'hidden'}\u003e\n        \u003cCounter /\u003e\n      \u003c/Activity\u003e\n    \u003c/div\u003e\n  );\n};\n\nReactDOM.createRoot(document.getElementById('root')!).render(\u003cApp /\u003e);\n```\n\n### Use with React.lazy\n\n\u003e Since Activity is implemented based on Suspense, please pay attention to placing the Suspense component under the Activity component when using it, otherwise it may cause the problem that the fallback cannot be displayed normally.\n\n```typescript\nimport { useState, lazy, Suspense } from 'react';\nimport ReactDOM from 'react-dom/client';\nimport { Activity } from '@ivliu/react-offscreen';\n\nconst LazyCount = lazy(() =\u003e import('./Count')); \n\nconst Count = () =\u003e {\n  const [count, setCount] = useState(0);\n\n  return \u003cp onClick={() =\u003e setCount(count + 1)}\u003e{count}\u003c/p\u003e;\n};\n\nconst App = () =\u003e {\n  const [open, setOpen] = useState(false);\n  return (\n    \u003cdiv\u003e\n      \u003cbutton onClick={() =\u003e setVisible(!open)}\u003e{open}\u003c/button\u003e\n      \u003cActivity mode={open ? 'visible' : 'hidden'}\u003e\n        \u003cSuspense fallback=\"loading...\"\u003e\n          \u003cLazyCount /\u003e\n        \u003c/Suspense\u003e\n      \u003c/Activity\u003e\n    \u003c/div\u003e\n  );\n};\n\nReactDOM.createRoot(document.getElementById('root')!).render(\u003cApp /\u003e);\n```\n\n## Rename to Activity\n\n\u003e In order to keep pace with the official react, we renamed Offscreen to Activity. At the same time, we will still export Offscreen\n\n```typescript\nimport { useState } from 'react';\nimport ReactDOM from 'react-dom/client';\nimport { Activity, Offscreen } from '@ivliu/react-offscreen';\n\nconst Count = () =\u003e {\n  const [count, setCount] = useState(0);\n\n  return \u003cp onClick={() =\u003e setCount(count + 1)}\u003e{count}\u003c/p\u003e;\n};\n\nconst App = () =\u003e {\n  const [open, setOpen] = useState(false);\n\n  return (\n    \u003cdiv\u003e\n      \u003cbutton onClick={() =\u003e setVisible(!open)}\u003e{open}\u003c/button\u003e\n      \u003cActivity mode={open ? 'visible' : 'hidden'}\u003e\n        \u003cCount /\u003e\n      \u003c/Activity\u003e\n      \u003cOffscreen mode={open ? 'visible' : 'hidden'}\u003e\n        \u003cCount /\u003e\n      \u003c/Offscreen\u003e\n    \u003c/div\u003e\n  );\n};\n\nReactDOM.createRoot(document.getElementById('root')!).render(\u003cApp /\u003e);\n```\n\n## typescript\n\n```typescript\nimport { useState } from 'react';\nimport ReactDOM from 'react-dom/client';\nimport { Activity } from '@ivliu/react-offscreen';\nimport type { ActivityMode } from '@ivliu/react-offscreen';\n\nconst Count = () =\u003e {\n  const [count, setCount] = useState(0);\n\n  return \u003cp onClick={() =\u003e setCount(count + 1)}\u003e{count}\u003c/p\u003e;\n};\n\nconst App = () =\u003e {\n  const [mode, setMode] = useState\u003cActivityMode\u003e('visible');\n\n  return (\n    \u003cdiv\u003e\n      \u003cbutton onClick={() =\u003e setMode(mode === 'visible' ? 'hidden' : 'visible')}\u003e{mode}\u003c/button\u003e\n      \u003cActivity mode={mode}\u003e\n        \u003cCount /\u003e\n      \u003c/Activity\u003e\n    \u003c/div\u003e\n  );\n};\n\nReactDOM.createRoot(document.getElementById('root')!).render(\u003cApp /\u003e);\n```\n\n## unstable hooks\n\n\u003e We provide hook implementation for component activation and deactivation status, but we do not plan to merge it into the main branch. If you need it, please refer to https://github.com/IVLIU/react-offscreen/tree/feat/unstable-hooks\n\n```typescript\nimport React from 'react';\nimport ReactDOM from 'react-dom/client';\nimport { Offscreen, useActivated } from 'react-offscreen';\n\nconst Count = () =\u003e {\n  const [count, setCount] = React.useState(0);\n\n  useActivated(() =\u003e {\n    console.log('activated');\n    return () =\u003e {\n      console.log('deactivated')\n    }\n  });\n\n  return \u003cp onClick={() =\u003e setCount(count + 1)}\u003e{count}\u003c/p\u003e;\n};\n\nconst App = () =\u003e {\n  const [visible, setVisible] = React.useState(false);\n  return (\n    \u003cdiv\u003e\n      \u003cbutton onClick={() =\u003e setVisible(!visible)}\u003e{visible}\u003c/button\u003e\n      \u003cOffscreen mode={visible ? 'visible' : 'hidden'}\u003e\n        \u003cCount /\u003e\n      \u003c/Offscreen\u003e\n    \u003c/div\u003e\n  );\n};\n\nReactDOM.createRoot(document.getElementById('root')!).render(\u003cApp /\u003e);\n```\n\n## Notice\n\nplease use react16.8 and above versions","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivliu%2Freact-offscreen","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fivliu%2Freact-offscreen","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivliu%2Freact-offscreen/lists"}