├── .gitignore ├── LICENSE ├── README.md ├── package.json ├── src └── index.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/macos,vscode 3 | # Edit at https://www.gitignore.io/?templates=macos,vscode 4 | 5 | ### macOS ### 6 | # General 7 | .DS_Store 8 | .AppleDouble 9 | .LSOverride 10 | 11 | # Icon must end with two \r 12 | Icon 13 | 14 | # Thumbnails 15 | ._* 16 | 17 | # Files that might appear in the root of a volume 18 | .DocumentRevisions-V100 19 | .fseventsd 20 | .Spotlight-V100 21 | .TemporaryItems 22 | .Trashes 23 | .VolumeIcon.icns 24 | .com.apple.timemachine.donotpresent 25 | 26 | # Directories potentially created on remote AFP share 27 | .AppleDB 28 | .AppleDesktop 29 | Network Trash Folder 30 | Temporary Items 31 | .apdisk 32 | node_modules 33 | 34 | #!! ERROR: vscode is undefined. Use list command to see defined gitignore types !!# 35 | 36 | # End of https://www.gitignore.io/api/macos,vscode 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Tejas Kumar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `useIntersectionObserver` 2 | This simple [React](https://reactjs.org/) [Hook](https://reactjs.org/docs/hooks-intro.html) uses the [Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) API in order to relay information to your UI about whether a given element is **intersecting** with the viewport. 3 | 4 | ## Getting Started 5 | 6 | Firstly, you'll want to `yarn add react-hook-intersection-observer` into your project. 7 | 8 | Then, using this is as simple as: 9 | 10 | [![Edit react-hook-intersection-observer](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/r45lrl8rzm) 11 | 12 | ```jsx 13 | import React, { useRef, useState } from "react"; 14 | import { useIntersectionObserver } from "react-hook-intersection-observer"; 15 | 16 | const App = () => { 17 | const root = useRef(); // We need a ref to our "root" or our parent, 18 | const target = useRef(); // We need a ref to our "target" or our child-to-watch, 19 | 20 | // Let's use a bit of state. 21 | const [isThingIntersecting, setThingIntersecting] = useState(false); 22 | 23 | // Here's our hook! Let's give it some configuration... 24 | useIntersectionObserver({ 25 | root, 26 | target, 27 | 28 | // What do we do when it intersects? 29 | // The signature of this callback is (collectionOfIntersections, observerElement). 30 | onIntersect: ([{ isIntersecting }]) => setThingIntersecting(isIntersecting) 31 | }); 32 | 33 | return ( 34 |
35 |

useIntersectionObserver

36 |

37 | The thing is currently{" "} 38 | 39 | {!isThingIntersecting && not}{" "} 40 | 41 | 42 | intersecting 43 | 44 | 45 | ! 46 |

47 | 48 | 49 |
50 |
51 |
THE THING
52 |
53 |
54 |
55 | ); 56 | }; 57 | ``` 58 | 59 | ## Contributing 60 | 61 | This project is _totally_ open for contributions. Get started by looking at the list of [open issues](https://github.com/tejasq/react-hook-intersection-observer/issues), or by opening one and we can talk about improvements! Wooo! 62 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-hook-intersection-observer", 3 | "description": "A simple React Hook that uses the Intersection Observer API", 4 | "keywords": [ 5 | "react", 6 | "hooks", 7 | "react hooks", 8 | "intersection observer" 9 | ], 10 | "bugs": { 11 | "email": "tejas@tejas.qa", 12 | "url": "https://github.com/tejasq/react-hook-intersection-observer" 13 | }, 14 | "author": { 15 | "email": "tejas@tejas.qa", 16 | "name": "Tejas Kumar", 17 | "url": "https://twitter.com/tejaskumar_" 18 | }, 19 | "contributors": [ 20 | { 21 | "email": "tejas@tejas.qa", 22 | "name": "Tejas Kumar", 23 | "url": "https://twitter.com/tejaskumar_" 24 | } 25 | ], 26 | "repository": { 27 | "type": "git", 28 | "url": "https://github.com/tejasq/react-hook-intersection-observer" 29 | }, 30 | "version": "0.1.0", 31 | "main": "src/index.js", 32 | "license": "MIT", 33 | "dependencies": { 34 | "react": "^16.7.0-alpha.2" 35 | }, 36 | "peerDependencies": { 37 | "react": "^16.7.0-alpha.2" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import { useEffect } from "react"; 2 | 3 | export const useIntersectionObserver = ({ root, target, onIntersect, threshold = 1.0, rootMargin = "0px" }) => { 4 | useEffect( 5 | () => { 6 | 7 | if (!root) { 8 | console.warn( 9 | `No "root" specified for Intersection Observer. 10 | 11 | useIntersectionObserver needs to be called with an initial configuration, 12 | where you'd pass in a "root" value (a React Ref using the useRef hook) 13 | to an element that contains a child that would intersect with it: a 14 | container that's aware of its children. 15 | 16 | Please add a root option and try again. 17 | 18 | More info: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#Creating_an_intersection_observer`); 19 | return; 20 | } 21 | 22 | const observer = new IntersectionObserver(onIntersect, { 23 | root: root.current, 24 | rootMargin, 25 | threshold, 26 | }); 27 | 28 | if (!target) { 29 | console.warn( 30 | `No target specified for Intersection Observer. 31 | 32 | useIntersectionObserver needs to be called with an initial configuration, 33 | where you'd pass in a "target" value (a React Ref using the useRef hook) that 34 | represents an element that is contained inside a root element that will be 35 | tracked. 36 | 37 | Please add a target option and try again. 38 | 39 | More info: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#Creating_an_intersection_observer`); 40 | return; 41 | } 42 | 43 | observer.observe(target.current); 44 | 45 | // Let's clean up after ourselves. 46 | return () => { 47 | observer.unobserve(target.current); 48 | }; 49 | } 50 | ); 51 | }; 52 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "js-tokens@^3.0.0 || ^4.0.0": 6 | version "4.0.0" 7 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" 8 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 9 | 10 | loose-envify@^1.1.0, loose-envify@^1.3.1: 11 | version "1.4.0" 12 | resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" 13 | integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== 14 | dependencies: 15 | js-tokens "^3.0.0 || ^4.0.0" 16 | 17 | object-assign@^4.1.1: 18 | version "4.1.1" 19 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 20 | integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= 21 | 22 | prop-types@^15.6.2: 23 | version "15.6.2" 24 | resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" 25 | integrity sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ== 26 | dependencies: 27 | loose-envify "^1.3.1" 28 | object-assign "^4.1.1" 29 | 30 | react@^16.7.0-alpha.2: 31 | version "16.7.0-alpha.2" 32 | resolved "https://registry.yarnpkg.com/react/-/react-16.7.0-alpha.2.tgz#924f2ae843a46ea82d104a8def7a599fbf2c78ce" 33 | integrity sha512-Xh1CC8KkqIojhC+LFXd21jxlVtzoVYdGnQAi/I2+dxbmos9ghbx5TQf9/nDxc4WxaFfUQJkya0w1k6rMeyIaxQ== 34 | dependencies: 35 | loose-envify "^1.1.0" 36 | object-assign "^4.1.1" 37 | prop-types "^15.6.2" 38 | scheduler "^0.12.0-alpha.2" 39 | 40 | scheduler@^0.12.0-alpha.2: 41 | version "0.12.0-alpha.2" 42 | resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.12.0-alpha.2.tgz#2a8bc8dc6ecdb75fa6480ceeedc1f187c9539970" 43 | integrity sha512-bfqFzGH18MjjhePIzYQNR0uGQ1wMCX6Q83c2s+3fzyuqKT6zBI2wNQTpq01q72C7QItAp8if5w2LfMiXnI2SYw== 44 | dependencies: 45 | loose-envify "^1.1.0" 46 | object-assign "^4.1.1" 47 | --------------------------------------------------------------------------------