{"id":13422369,"url":"https://github.com/thebuilder/react-intersection-observer","last_synced_at":"2025-05-12T05:28:12.163Z","repository":{"id":37405412,"uuid":"90013055","full_name":"thebuilder/react-intersection-observer","owner":"thebuilder","description":"React implementation of the Intersection Observer API to tell you when an element enters or leaves the viewport.","archived":false,"fork":false,"pushed_at":"2025-04-30T19:18:26.000Z","size":7292,"stargazers_count":5304,"open_issues_count":2,"forks_count":189,"subscribers_count":18,"default_branch":"main","last_synced_at":"2025-05-12T02:43:05.316Z","etag":null,"topics":["hook","hooks","intersection-observer","intersectionobserver","intersectionobserver-api","lazy-loading","monitor","performance","react","react-hooks","reactjs","scrolling","viewport","visibility"],"latest_commit_sha":null,"homepage":"https://react-intersection-observer.vercel.app","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/thebuilder.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":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-05-02T09:05:52.000Z","updated_at":"2025-05-11T13:20:03.000Z","dependencies_parsed_at":"2024-01-21T23:41:53.065Z","dependency_job_id":"f6aec568-bea6-454c-86ce-c3468a4950e2","html_url":"https://github.com/thebuilder/react-intersection-observer","commit_stats":{"total_commits":696,"total_committers":48,"mean_commits":14.5,"dds":0.4367816091954023,"last_synced_commit":"f3213ddac865abf7c10fa22042d793250b657d7d"},"previous_names":[],"tags_count":171,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thebuilder%2Freact-intersection-observer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thebuilder%2Freact-intersection-observer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thebuilder%2Freact-intersection-observer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thebuilder%2Freact-intersection-observer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thebuilder","download_url":"https://codeload.github.com/thebuilder/react-intersection-observer/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253672701,"owners_count":21945480,"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":["hook","hooks","intersection-observer","intersectionobserver","intersectionobserver-api","lazy-loading","monitor","performance","react","react-hooks","reactjs","scrolling","viewport","visibility"],"created_at":"2024-07-30T23:00:42.906Z","updated_at":"2025-05-12T05:28:12.142Z","avatar_url":"https://github.com/thebuilder.png","language":"TypeScript","readme":"# react-intersection-observer\n\n[![Version Badge][npm-version-svg]][package-url]\n[![GZipped size][npm-minzip-svg]][bundlephobia-url]\n[![Test][test-image]][test-url]\n[![License][license-image]][license-url]\n[![Downloads][downloads-image]][downloads-url]\n\nReact implementation of the\n[Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API)\nto tell you when an element enters or leaves the viewport. Contains both a\n[Hooks](#useinview-hook), [render props](#render-props) and\n[plain children](#plain-children) implementation.\n\n## Features\n\n- 🪝 **Hooks or Component API** - With `useInView` it's easier than ever to\n  monitor elements\n- ⚡️ **Optimized performance** - Reuses Intersection Observer instances where\n  possible\n- ⚙️ **Matches native API** - Intuitive to use\n- 🛠 **Written in TypeScript** - It'll fit right into your existing TypeScript\n  project\n- 🧪 **Ready to test** - Mocks the Intersection Observer for easy testing with\n  [Jest](https://jestjs.io/) or [Vitest](https://vitest.dev/)\n- 🌳 **Tree-shakeable** - Only include the parts you use\n- 💥 **Tiny bundle** - Around **~1.15kB** for `useInView` and **~1.6kB** for\n  `\u003cInView\u003e`\n\n[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/thebuilder/react-intersection-observer)\n\n## Installation\n\nInstall the package with your package manager of choice:\n\n```sh\nnpm install react-intersection-observer --save\n```\n\n## Usage\n\n### `useInView` hook\n\n```js\n// Use object destructuring, so you don't need to remember the exact order\nconst { ref, inView, entry } = useInView(options);\n\n// Or array destructuring, making it easy to customize the field names\nconst [ref, inView, entry] = useInView(options);\n```\n\nThe `useInView` hook makes it easy to monitor the `inView` state of your\ncomponents. Call the `useInView` hook with the (optional) [options](#options)\nyou need. It will return an array containing a `ref`, the `inView` status and\nthe current\n[`entry`](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry).\nAssign the `ref` to the DOM element you want to monitor, and the hook will\nreport the status.\n\n```jsx\nimport React from \"react\";\nimport { useInView } from \"react-intersection-observer\";\n\nconst Component = () =\u003e {\n  const { ref, inView, entry } = useInView({\n    /* Optional options */\n    threshold: 0,\n  });\n\n  return (\n    \u003cdiv ref={ref}\u003e\n      \u003ch2\u003e{`Header inside viewport ${inView}.`}\u003c/h2\u003e\n    \u003c/div\u003e\n  );\n};\n```\n\n### Render props\n\nTo use the `\u003cInView\u003e` component, you pass it a function. It will be called\nwhenever the state changes, with the new value of `inView`. In addition to the\n`inView` prop, children also receive a `ref` that should be set on the\ncontaining DOM element. This is the element that the Intersection Observer will\nmonitor.\n\nIf you need it, you can also access the\n[`IntersectionObserverEntry`](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry)\non `entry`, giving you access to all the details about the current intersection\nstate.\n\n```jsx\nimport { InView } from \"react-intersection-observer\";\n\nconst Component = () =\u003e (\n  \u003cInView\u003e\n    {({ inView, ref, entry }) =\u003e (\n      \u003cdiv ref={ref}\u003e\n        \u003ch2\u003e{`Header inside viewport ${inView}.`}\u003c/h2\u003e\n      \u003c/div\u003e\n    )}\n  \u003c/InView\u003e\n);\n\nexport default Component;\n```\n\n### Plain children\n\nYou can pass any element to the `\u003cInView /\u003e`, and it will handle creating the\nwrapping DOM element. Add a handler to the `onChange` method, and control the\nstate in your own component. Any extra props you add to `\u003cInView\u003e` will be\npassed to the HTML element, allowing you set the `className`, `style`, etc.\n\n```jsx\nimport { InView } from \"react-intersection-observer\";\n\nconst Component = () =\u003e (\n  \u003cInView as=\"div\" onChange={(inView, entry) =\u003e console.log(\"Inview:\", inView)}\u003e\n    \u003ch2\u003ePlain children are always rendered. Use onChange to monitor state.\u003c/h2\u003e\n  \u003c/InView\u003e\n);\n\nexport default Component;\n```\n\n\u003e [!NOTE]\n\u003e When rendering a plain child, make sure you keep your HTML output\n\u003e semantic. Change the `as` to match the context, and add a `className` to style\n\u003e the `\u003cInView /\u003e`. The component does not support Ref Forwarding, so if you\n\u003e need a `ref` to the HTML element, use the Render Props version instead.\n\n## API\n\n### Options\n\nProvide these as the options argument in the `useInView` hook or as props on the\n**`\u003cInView /\u003e`** component.\n\n| Name                   | Type                      | Default     | Description                                                                                                                                                                                                                                                                                     |\n| ---------------------- | ------------------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **root**               | `Element`                 | `document`  | The Intersection Observer interface's read-only root property identifies the Element or Document whose bounds are treated as the bounding box of the viewport for the element which is the observer's target. If the root is `null`, then the bounds of the actual document viewport are used.  |\n| **rootMargin**         | `string`                  | `'0px'`     | Margin around the root. Can have values similar to the CSS margin property, e.g. `\"10px 20px 30px 40px\"` (top, right, bottom, left). Also supports percentages, to check if an element intersects with the center of the viewport for example `\"-50% 0% -50% 0%\"`.                              |\n| **threshold**          | `number` or `number[]`    | `0`         | Number between `0` and `1` indicating the percentage that should be visible before triggering. Can also be an array of numbers, to create multiple trigger points.                                                                                                                              |\n| **onChange**           | `(inView, entry) =\u003e void` | `undefined` | Call this function whenever the in view state changes. It will receive the `inView` boolean, alongside the current `IntersectionObserverEntry`.                                                                                                                                                 |\n| **trackVisibility** 🧪 | `boolean`                 | `false`     | A boolean indicating whether this Intersection Observer will track visibility changes on the target.                                                                                                                                                                                            |\n| **delay** 🧪           | `number`                  | `undefined` | A number indicating the minimum delay in milliseconds between notifications from this observer for a given target. This must be set to at least `100` if `trackVisibility` is `true`.                                                                                                           |\n| **skip**               | `boolean`                 | `false`     | Skip creating the IntersectionObserver. You can use this to enable and disable the observer as needed. If `skip` is set while `inView`, the current state will still be kept.                                                                                                                   |\n| **triggerOnce**        | `boolean`                 | `false`     | Only trigger the observer once.                                                                                                                                                                                                                                                                 |\n| **initialInView**      | `boolean`                 | `false`     | Set the initial value of the `inView` boolean. This can be used if you expect the element to be in the viewport to start with, and you want to trigger something when it leaves.                                                                                                                |\n| **fallbackInView**     | `boolean`                 | `undefined` | If the `IntersectionObserver` API isn't available in the client, the default behavior is to throw an Error. You can set a specific fallback behavior, and the `inView` value will be set to this instead of failing. To set a global default, you can set it with the `defaultFallbackInView()` |\n\n### InView Props\n\nThe **`\u003cInView /\u003e`** component also accepts the following props:\n\n| Name         | Type                                                 | Default     | Description                                                                                                                                                                                                                                                                                                                    |\n| ------------ | ---------------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| **as**       | `IntrinsicElement`                                   | `'div'`     | Render the wrapping element as this element. Defaults to `div`. If you want to use a custom component, please use the `useInView` hook or a render prop instead to manage the reference explictly.                                                                                                                             |\n| **children** | `({ref, inView, entry}) =\u003e ReactNode` or `ReactNode` | `undefined` | Children expects a function that receives an object containing the `inView` boolean and a `ref` that should be assigned to the element root. Alternatively pass a plain child, to have the `\u003cInView /\u003e` deal with the wrapping element. You will also get the `IntersectionObserverEntry` as `entry`, giving you more details. |\n\n### Intersection Observer v2 🧪\n\nThe new\n[v2 implementation of IntersectionObserver](https://developers.google.com/web/updates/2019/02/intersectionobserver-v2)\nextends the original API, so you can track if the element is covered by another\nelement or has filters applied to it. Useful for blocking clickjacking attempts\nor tracking ad exposure.\n\nTo use it, you'll need to add the new `trackVisibility` and `delay` options.\nWhen you get the `entry` back, you can then monitor if `isVisible` is `true`.\n\n```jsx\nconst TrackVisible = () =\u003e {\n  const { ref, entry } = useInView({ trackVisibility: true, delay: 100 });\n  return \u003cdiv ref={ref}\u003e{entry?.isVisible}\u003c/div\u003e;\n};\n```\n\nThis is still a very new addition, so check\n[caniuse](https://caniuse.com/#feat=intersectionobserver-v2) for current browser\nsupport. If `trackVisibility` has been set, and the current browser doesn't\nsupport it, a fallback has been added to always report `isVisible` as `true`.\n\nIt's not added to the TypeScript `lib.d.ts` file yet, so you will also have to\nextend the `IntersectionObserverEntry` with the `isVisible` boolean.\n\n## Recipes\n\nThe `IntersectionObserver` itself is just a simple but powerful tool. Here's a\nfew ideas for how you can use it.\n\n- [Lazy image load](docs/Recipes.md#lazy-image-load)\n- [Trigger animations](docs/Recipes.md#trigger-animations)\n- [Track impressions](docs/Recipes.md#track-impressions) _(Google Analytics, Tag\n  Manager, etc.)_\n\n## FAQ\n\n### How can I assign multiple refs to a component?\n\nYou can wrap multiple `ref` assignments in a single `useCallback`:\n\n```jsx\nimport React, { useRef, useCallback } from \"react\";\nimport { useInView } from \"react-intersection-observer\";\n\nfunction Component(props) {\n  const ref = useRef();\n  const { ref: inViewRef, inView } = useInView();\n\n  // Use `useCallback` so we don't recreate the function on each render\n  const setRefs = useCallback(\n    (node) =\u003e {\n      // Ref's from useRef needs to have the node assigned to `current`\n      ref.current = node;\n      // Callback refs, like the one from `useInView`, is a function that takes the node as an argument\n      inViewRef(node);\n    },\n    [inViewRef],\n  );\n\n  return \u003cdiv ref={setRefs}\u003eShared ref is visible: {inView}\u003c/div\u003e;\n}\n```\n\n### `rootMargin` isn't working as expected\n\nWhen using `rootMargin`, the margin gets added to the current `root` - If your\napplication is running inside a `\u003ciframe\u003e`, or you have defined a custom `root`\nthis will not be the current viewport.\n\nYou can read more about this on these links:\n\n- [Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#The_intersection_root_and_root_margin)\n- [w3c/IntersectionObserver: rootMargin ignored within iframe](https://github.com/w3c/IntersectionObserver/issues/283#issuecomment-507397917)\n- [w3c/IntersectionObserver: Cannot track intersection with an iframe's viewport](https://github.com/w3c/IntersectionObserver/issues/372)\n- [w3c/Support iframe viewport tracking](https://github.com/w3c/IntersectionObserver/pull/465)\n\n## Testing\n\n\u003e [!TIP]\n\u003e Consider using [Vitest Browser Mode](https://vitest.dev/guide/browser/) instead of `jsdom` or `happy-dom`.\n\u003e This option allows you to utilize the real browser implementation and triggers correctly when scrolling or adding elements to the viewport. You can skip the `react-intersection-observer/test-utils`, or use it as needed.\n\nIn order to write meaningful tests, the `IntersectionObserver` needs to be\nmocked. You can use the included `react-intersection-observer/test-utils` to\nhelp with this. It mocks the `IntersectionObserver`, and includes a few methods\nto assist with faking the `inView` state. When setting the `isIntersecting`\nvalue you can pass either a `boolean` value or a threshold between 0 and 1. It\nwill emulate the real IntersectionObserver, allowing you to validate that your\ncomponents are behaving as expected.\n\n| Method                                        | Description                                                                                                                                                                       |\n|-----------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `mockAllIsIntersecting(isIntersecting)`       | Set `isIntersecting` on all current Intersection Observer instances. The value of `isIntersecting` should be either a `boolean` or a threshold between 0 and 1.                   |\n| `mockIsIntersecting(element, isIntersecting)` | Set `isIntersecting` for the Intersection Observer of a specific `element`. The value of `isIntersecting` should be either a `boolean` or a threshold between 0 and 1.            |\n| `intersectionMockInstance(element)`           | Call the `intersectionMockInstance` method with an element, to get the (mocked) `IntersectionObserver` instance. You can use this to spy on the `observe` and`unobserve` methods. |\n| `setupIntersectionMocking(mockFn)`            | Mock the `IntersectionObserver`, so we can interact with them in tests - Should be called in `beforeEach`. (**Done automatically in Jest environment**)                           |\n| `resetIntersectionMocking()`                  | Reset the mocks on `IntersectionObserver` - Should be called in `afterEach`. (**Done automatically in Jest/Vitest environment**)                                                  |\n| `destroyIntersectionMocking()`                | Destroy the mocked `IntersectionObserver` function, and return `window.IntersectionObserver` to the original browser implementation                                               |\n\n### Testing Libraries\n\nThis library comes with built-in support for writing tests in both\n[Jest](https://jestjs.io/) and [Vitest](https://vitest.dev/)\n\n#### Jest\n\nTesting with Jest should work out of the box. Just import the\n`react-intersection-observer/test-utils` in your test files, and you can use the\nmocking methods.\n\n#### Vitest\n\nIf you're running Vitest with [globals](https://vitest.dev/config/#globals),\nthen it'll automatically mock the IntersectionObserver, just like running with\nJest. Otherwise, you'll need to manually setup/reset the mocking in either the\nindividual tests, or a [setup file](https://vitest.dev/config/#setupfiles).\n\n```js\nimport { vi, beforeEach, afterEach } from \"vitest\";\nimport {\n  setupIntersectionMocking,\n  resetIntersectionMocking,\n} from \"react-intersection-observer/test-utils\";\n\nbeforeEach(() =\u003e {\n  setupIntersectionMocking(vi.fn);\n});\n\nafterEach(() =\u003e {\n  resetIntersectionMocking();\n});\n```\n\nYou only need to do this if the test environment does not support `beforeEach`\nglobally, alongside either `jest.fn` or `vi.fn`.\n\n#### Other Testing Libraries\n\nSee the instructions for [Vitest](#vitest). You should be able to use a similar\nsetup/reset code, adapted to the testing library you are using. Failing that,\ncopy the code from [test-utils.ts][test-utils-url], and make your own version.\n\n### Fallback Behavior\n\nYou can create a\n[Jest setup file](https://jestjs.io/docs/configuration#setupfilesafterenv-array)\nthat leverages the\n[unsupported fallback](https://github.com/thebuilder/react-intersection-observer#unsupported-fallback)\noption. In this case, you can override the `IntersectionObserver` in test files\nwere you actively import `react-intersection-observer/test-utils`.\n\n**test-setup.js**\n\n```js\nimport { defaultFallbackInView } from \"react-intersection-observer\";\n\ndefaultFallbackInView(true); // or `false` - whichever consistent behavior makes the most sense for your use case.\n```\n\nAlternatively, you can mock the Intersection Observer in all tests with a global\nsetup file. Add `react-intersection-observer/test-utils` to\n[setupFilesAfterEnv](https://jestjs.io/docs/configuration#setupfilesafterenv-array)\nin the Jest config, or [setupFiles](https://vitest.dev/config/#setupfiles) in\nVitest.\n\n```js\nmodule.exports = {\n  setupFilesAfterEnv: [\"react-intersection-observer/test-utils\"],\n};\n```\n\n### Test Example\n\n```js\nimport React from \"react\";\nimport { screen, render } from \"@testing-library/react\";\nimport { useInView } from \"react-intersection-observer\";\nimport {\n  mockAllIsIntersecting,\n  mockIsIntersecting,\n  intersectionMockInstance,\n} from \"react-intersection-observer/test-utils\";\n\nconst HookComponent = ({ options }) =\u003e {\n  const { ref, inView } = useInView(options);\n  return (\n    \u003cdiv ref={ref} data-testid=\"wrapper\"\u003e\n      {inView.toString()}\n    \u003c/div\u003e\n  );\n};\n\ntest(\"should create a hook inView\", () =\u003e {\n  render(\u003cHookComponent /\u003e);\n\n  // This causes all (existing) IntersectionObservers to be set as intersecting\n  mockAllIsIntersecting(true);\n  screen.getByText(\"true\");\n});\n\ntest(\"should create a hook inView with threshold\", () =\u003e {\n  render(\u003cHookComponent options={{ threshold: 0.3 }} /\u003e);\n\n  mockAllIsIntersecting(0.1);\n  screen.getByText(\"false\");\n\n  // Once the threshold has been passed, it will trigger inView.\n  mockAllIsIntersecting(0.3);\n  screen.getByText(\"true\");\n});\n\ntest(\"should mock intersecing on specific hook\", () =\u003e {\n  render(\u003cHookComponent /\u003e);\n  const wrapper = screen.getByTestId(\"wrapper\");\n\n  // Set the intersection state on the wrapper.\n  mockIsIntersecting(wrapper, 0.5);\n  screen.getByText(\"true\");\n});\n\ntest(\"should create a hook and call observe\", () =\u003e {\n  const { getByTestId } = render(\u003cHookComponent /\u003e);\n  const wrapper = getByTestId(\"wrapper\");\n  // Access the `IntersectionObserver` instance for the wrapper Element.\n  const instance = intersectionMockInstance(wrapper);\n\n  expect(instance.observe).toHaveBeenCalledWith(wrapper);\n});\n```\n\n## Intersection Observer\n\n[Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API)\nis the API used to determine if an element is inside the viewport or not.\n[Browser support is excellent](http://caniuse.com/#feat=intersectionobserver) -\nWith\n[Safari adding support in 12.1](https://webkit.org/blog/8718/new-webkit-features-in-safari-12-1/),\nall major browsers now support Intersection Observers natively. Add the\npolyfill, so it doesn't break on older versions of iOS and IE11.\n\n### Unsupported fallback\n\nIf the client doesn't have support for the `IntersectionObserver`, then the\ndefault behavior is to throw an error. This will crash the React application,\nunless you capture it with an Error Boundary.\n\nIf you prefer, you can set a fallback `inView` value to use if the\n`IntersectionObserver` doesn't exist. This will make\n`react-intersection-observer` fail gracefully, but you must ensure your\napplication can correctly handle all your observers firing either `true` or\n`false` at the same time.\n\nYou can set the fallback globally:\n\n```js\nimport { defaultFallbackInView } from \"react-intersection-observer\";\n\ndefaultFallbackInView(true); // or 'false'\n```\n\nYou can also define the fallback locally on `useInView` or `\u003cInView\u003e` as an\noption. This will override the global fallback value.\n\n```jsx\nimport React from \"react\";\nimport { useInView } from \"react-intersection-observer\";\n\nconst Component = () =\u003e {\n  const { ref, inView, entry } = useInView({\n    fallbackInView: true,\n  });\n\n  return (\n    \u003cdiv ref={ref}\u003e\n      \u003ch2\u003e{`Header inside viewport ${inView}.`}\u003c/h2\u003e\n    \u003c/div\u003e\n  );\n};\n```\n\n### Polyfill\n\nYou can import the\n[polyfill](https://www.npmjs.com/package/intersection-observer) directly or use\na service like [https://cdnjs.cloudflare.com/polyfill](https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js) to add it when\nneeded.\n\n```sh\nyarn add intersection-observer\n```\n\nThen import it in your app:\n\n```js\nimport \"intersection-observer\";\n```\n\nIf you are using Webpack (or similar) you could use\n[dynamic imports](https://webpack.js.org/api/module-methods/#dynamic-expressions-in-import),\nto load the Polyfill only if needed. A basic implementation could look something\nlike this:\n\n```js\n/**\n * Do feature detection, to figure out which polyfills needs to be imported.\n **/\nasync function loadPolyfills() {\n  if (typeof window.IntersectionObserver === \"undefined\") {\n    await import(\"intersection-observer\");\n  }\n}\n```\n\n## Low level API\n\nYou can access the [`observe`](src/observe.ts) method, that\n`react-intersection-observer` uses internally to create and destroy\nIntersectionObserver instances. This allows you to handle more advanced use\ncases, where you need full control over when and how observers are created.\n\n```js\nimport { observe } from \"react-intersection-observer\";\n\nconst destroy = observe(element, callback, options);\n```\n\n| Name         | Type                       | Required | Description                                                |\n| ------------ | -------------------------- | -------- | ---------------------------------------------------------- |\n| **element**  | `Element`                  | true     | DOM element to observe                                     |\n| **callback** | `ObserverInstanceCallback` | true     | The callback function that Intersection Observer will call |\n| **options**  | `IntersectionObserverInit` | false    | The options for the Intersection Observer                  |\n\nThe `observe` method returns an `unobserve` function, that you must call in\norder to destroy the observer again.\n\n\u003e [!IMPORTANT]\n\u003e You most likely won't need this, but it can be useful if you\n\u003e need to handle IntersectionObservers outside React, or need full control over\n\u003e how instances are created.\n\n[package-url]: https://npmjs.org/package/react-intersection-observer\n[npm-version-svg]: https://img.shields.io/npm/v/react-intersection-observer.svg\n[npm-minzip-svg]: https://img.shields.io/bundlephobia/minzip/react-intersection-observer.svg\n[bundlephobia-url]: https://bundlephobia.com/result?p=react-intersection-observer\n[license-image]: http://img.shields.io/npm/l/react-intersection-observer.svg\n[license-url]: LICENSE\n[downloads-image]: http://img.shields.io/npm/dm/react-intersection-observer.svg\n[downloads-url]: http://npm-stat.com/charts.html?package=react-intersection-observer\n[test-image]: https://github.com/thebuilder/react-intersection-observer/workflows/Test/badge.svg\n[test-url]: https://github.com/thebuilder/react-intersection-observer/actions?query=workflow%3ATest\n[test-utils-url]: https://github.com/thebuilder/react-intersection-observer/blob/master/src/test-utils.ts\n","funding_links":[],"categories":["Developer Tools","UI Utilities","Packages","TypeScript","Components"],"sub_categories":["Reporter","Misc"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthebuilder%2Freact-intersection-observer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthebuilder%2Freact-intersection-observer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthebuilder%2Freact-intersection-observer/lists"}