{"id":20044801,"url":"https://github.com/roderickhsiao/react-in-viewport","last_synced_at":"2025-05-15T22:11:03.965Z","repository":{"id":37734766,"uuid":"84917238","full_name":"roderickhsiao/react-in-viewport","owner":"roderickhsiao","description":"Detect if React component is in viewport","archived":false,"fork":false,"pushed_at":"2025-04-15T21:24:00.000Z","size":5145,"stargazers_count":350,"open_issues_count":2,"forks_count":32,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-05-14T02:15:44.733Z","etag":null,"topics":["intersection-observer","lazyload","react","viewport"],"latest_commit_sha":null,"homepage":"https://roderickhsiao.github.io/react-in-viewport","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/roderickhsiao.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","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,"zenodo":null}},"created_at":"2017-03-14T07:10:33.000Z","updated_at":"2025-04-23T12:35:27.000Z","dependencies_parsed_at":"2024-05-02T10:54:41.606Z","dependency_job_id":"7b76060e-4c38-412d-a96c-650cd4579548","html_url":"https://github.com/roderickhsiao/react-in-viewport","commit_stats":{"total_commits":169,"total_committers":17,"mean_commits":9.941176470588236,"dds":0.6390532544378698,"last_synced_commit":"2f50b875b71c3c7d2e0ba253e9869b6bb26ac381"},"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roderickhsiao%2Freact-in-viewport","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roderickhsiao%2Freact-in-viewport/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roderickhsiao%2Freact-in-viewport/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roderickhsiao%2Freact-in-viewport/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/roderickhsiao","download_url":"https://codeload.github.com/roderickhsiao/react-in-viewport/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254430331,"owners_count":22069909,"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":["intersection-observer","lazyload","react","viewport"],"created_at":"2024-11-13T11:01:50.063Z","updated_at":"2025-05-15T22:11:03.939Z","avatar_url":"https://github.com/roderickhsiao.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003ch1\u003eReact In Viewport\u003c/h1\u003e\n  \u003ca href=\"https://www.npmjs.org/package/react-in-viewport\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/react-in-viewport.svg?style=flat\" alt=\"npm\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://unpkg.com/react-in-viewport\"\u003e\u003cimg src=\"https://img.badgesize.io/https://unpkg.com/react-in-viewport/dist/es/index.js?compression=gzip\" alt=\"gzip size\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/react-in-viewport\"\u003e\u003cimg src=\"https://img.shields.io/npm/dt/react-in-viewport.svg\" alt=\"downloads\" \u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003chr\u003e\n\nLibrary to detect whether or not a component is in the viewport, using the [Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API).\n\nThis library also uses [MutationObserver](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) to detect the change of the target element.\n\n```npm install --save react-in-viewport```\n\n```yarn add react-in-viewport```\n\n## Examples\n\n[Demo](https://roderickhsiao.github.io/react-in-viewport/)\n\n## Why\n\nA common use case is to load an image when a component is in the viewport ([lazy load](https://medium.com/@roderickhsiao/performance-101-i-know-how-to-load-images-a262d556250f)).\n\nWe have traditionally needed to monitor scroll position and calculate the viewport size, which can be a scroll performance bottleneck.\n\nModern browsers now provide a new API--[Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API)--which can make implementating this effort much easier and performant.\n\n\n## Polyfill\n\nFor browsers not supporting the API, you will need to load a [polyfill](https://www.npmjs.com/package/intersection-observer).\n[Browser support table](https://caniuse.com/#feat=intersectionobserver)\n\n```js\nrequire('intersection-observer');\n```\n\n## Design\n\nThe core logic is written using React Hooks. We provide two interfaces: you can use `handleViewport`, a higher order component (HOC) for class based components, or use hooks directly, for functional components.\n\nThe HOC acts as a wrapper and attaches the intersection observer to your target component. The HOC will then pass down extra props, indicating viewport information and executing a callback function when the component enters and leaves the viewport.\n\n## Usages\n\n### Using Higher Order Component\nWhen wrapping your component with `handleViewport` HOC, you will receive `inViewport` props indicating whether the component is in the viewport or not.\n\n`handleViewport` HOC accepts three params: `handleViewport(Component, Options, Config)`\n\n| Params    | Type          | Description                                                                                                                        |\n|-----------|---------------|------------------------------------------------------------------------------------------------------------------------------------|\n| Component | React Element | Callback function for when the component enters the viewport                                                                                    |\n| Options   | Object        | Options you want to pass to [Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) |   |\n| Config    | Object        | Configs for HOC (see below) |\n\n### Supported config\n\n| Params            | Type    | Default                                                                                                                            | Description                                  |\n|-------------------|---------|------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------|\n| disconnectOnLeave | boolean | false                                                                                                                              | Disconnect intersection observer after leave |\n\n### HOC Component Props\n\n| Props           | Type     | Default | Description                                     |\n|-----------------|----------|---------|-------------------------------------------------|\n| onEnterViewport | function |         | Callback function for when the component enters the viewport |\n| onLeaveViewport | function |         | Callback function for when the component leaves the viewport |\n\nThe HOC preserves `onEnterViewport` and `onLeaveViewport` props as a callback\n\n\n### Props passed down by HOC to your component\n\n| Props      | Type      | Default | Description                                                                       |\n|------------|-----------|---------|-----------------------------------------------------------------------------------|\n| inViewport | boolean   | false   | Whether your component is in the viewport                                                     |  \n| forwardedRef   | React ref |         | Assign this prop as a ref on your component |\n| enterCount | number    |         | Numbers of times your component has entered the viewport                                     |\n| leaveCount | number    |         | Number of times your component has left the viewport                                     |\n\n_NOTE_: Need to add `ref={this.props.forwardedRef}` to your component\n\n#### Example of a functional component\n\n```tsx\nimport handleViewport, { type InjectedViewportProps } from 'react-in-viewport';\n\nconst Block = (props: InjectedViewportProps\u003cHTMLDivElement\u003e) =\u003e {\n  const { inViewport, forwardedRef } = props;\n  const color = inViewport ? '#217ac0' : '#ff9800';\n  const text = inViewport ? 'In viewport' : 'Not in viewport';\n  return (\n    \u003cdiv className=\"viewport-block\" ref={forwardedRef}\u003e\n      \u003ch3\u003e{ text }\u003c/h3\u003e\n      \u003cdiv style={{ width: '400px', height: '300px', background: color }} /\u003e\n    \u003c/div\u003e\n  );\n};\n\nconst ViewportBlock = handleViewport(Block, /** options: {}, config: {} **/);\n\nconst Component = (props) =\u003e (\n  \u003cdiv\u003e\n    \u003cdiv style={{ height: '100vh' }}\u003e\n      \u003ch2\u003eScroll down to make component in viewport\u003c/h2\u003e\n    \u003c/div\u003e\n    \u003cViewportBlock onEnterViewport={() =\u003e console.log('enter')} onLeaveViewport={() =\u003e console.log('leave')} /\u003e\n  \u003c/div\u003e\n))\n```\n\n#### Example for enter/leave counts\n\n- If you need to know how many times the component has entered the viewport, use the prop `enterCount`.\n- If you need to know how many times the component has left the viewport, use the prop `leaveCount`.\n\n```javascript\nimport React, { Component } from 'react';\nimport handleViewport from 'react-in-viewport';\n\nclass MySectionBlock extends Component {\n  getStyle() {\n    const { inViewport, enterCount } = this.props;\n    //Fade in only the first time we enter the viewport\n    if (inViewport \u0026\u0026 enterCount === 1) {\n      return { WebkitTransition: 'opacity 0.75s ease-in-out' };\n    } else if (!inViewport \u0026\u0026 enterCount \u003c 1) {\n      return { WebkitTransition: 'none', opacity: '0' };\n    } else {\n      return {};\n    }\n  }\n\n  render() {\n    const { enterCount, leaveCount, forwardedRef } = this.props;\n    return (\n      \u003csection ref={forwardedRef}\u003e\n        \u003cdiv className=\"content\" style={this.getStyle()}\u003e\n          \u003ch1\u003eHello\u003c/h1\u003e\n          \u003cp\u003e{`Enter viewport: ${enterCount} times`}\u003c/p\u003e\n          \u003cp\u003e{`Leave viewport: ${leaveCount} times`}\u003c/p\u003e\n        \u003c/div\u003e\n      \u003c/section\u003e\n    );\n  }\n}\nconst MySection = handleViewport(MySectionBlock, { rootMargin: '-1.0px' });\n\nexport default MySection;\n```\n\n### Using Hooks\n\nAlternatively, you can also directly using `useInViewport` hook which takes similar configuration as HOC.\n\n```js\nimport React, { useRef } from 'react';\nimport { useInViewport } from 'react-in-viewport';\n\nconst MySectionBlock = () =\u003e {\n  const myRef = useRef(null);\n  const {\n    inViewport,\n    enterCount,\n    leaveCount,\n  } = useInViewport(\n    myRef,\n    options,\n    config = { disconnectOnLeave: false },\n    props\n  );\n\n  return (\n    \u003csection ref={myRef}\u003e\n      \u003cdiv className=\"content\" style={this.getStyle()}\u003e\n        \u003ch1\u003eHello\u003c/h1\u003e\n        \u003cp\u003e{`Enter viewport: ${enterCount} times`}\u003c/p\u003e\n        \u003cp\u003e{`Leave viewport: ${leaveCount} times`}\u003c/p\u003e\n      \u003c/div\u003e\n    \u003c/section\u003e\n  );\n};\n```\n\n## Who is using this component\n\n- [Tinder](https://tinder.com)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froderickhsiao%2Freact-in-viewport","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Froderickhsiao%2Freact-in-viewport","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froderickhsiao%2Freact-in-viewport/lists"}