`) or a
composite component (e.g. `
`).
Waypoint needs a DOM node to compute its boundaries. When you pass a DOM
component to Waypoint, it handles getting a reference to the DOM node through
the `ref` prop automatically.
If you pass a composite component, you can wrap it with `React.forwardRef` (requires `react@^16.3.0`)
and have the `ref` prop being handled automatically for you, like this:
```jsx
class Block extends React.Component {
render() {
return
Hello
}
}
const BlockWithRef = React.forwardRef((props, ref) => {
return
})
const App = () => (
)
```
If you can't do that because you are using older version of React then
you need to make use of the `innerRef` prop passed by Waypoint to your component.
Simply pass it through as the `ref` of a DOM component and you're all set. Like in
this example:
```jsx
class Block extends React.Component {
render() {
return
Hello
}
}
Block.propTypes = {
innerRef: PropTypes.func.isRequired,
}
const App = () => (
)
```
The `onEnter` callback will be called when *any* part of the child is visible
in the viewport. The `onLeave` callback will be called when *all* of the child
has exited the viewport.
(Note that this is measured only on a single axis. What this means is that for a
Waypoint within a vertically scrolling parent, it could be off of the screen
horizontally yet still fire an onEnter event, because it is within the vertical
boundaries).
Deciding whether to pass a child or not will depend on your use case. One
example of when passing a child is useful is for a scrollspy
(like [Bootstrap's](https://bootstrapdocs.com/v3.3.6/docs/javascript/#scrollspy)).
Imagine if you want to fire a waypoint when a particularly long piece of content
is visible onscreen. When the page loads, it is conceivable that both the top
and bottom of this piece of content could lie outside of the boundaries,
because the content is taller than the viewport. If you didn't pass a child,
and instead put the waypoint above or below the content, then you will not
receive an `onEnter` callback (nor any other callback from this library).
Instead, passing this long content as a child of the Waypoint would fire the `onEnter`
callback when the page loads.
## Containing elements and `scrollableAncestor`
React Waypoint positions its [boundaries](#offsets-and-boundaries) based on the
first scrollable ancestor of the Waypoint.
If that algorithm doesn't work for your use case, then you might find the
`scrollableAncestor` prop useful. It allows you to specify what the scrollable
ancestor is. Pass a reference to a DOM node as that prop, and the Waypoint will
use the scroll position of *that* node, rather than its first scrollable
ancestor.
This can also be the string "window", which can be useful if you are using
server rendering.
#### Example Usage
Sometimes, waypoints that are deeply nested in the DOM tree may need to track
the scroll position of the page as a whole. If you want to be sure that no other
scrollable ancestor is used (since, once again, the first scrollable ancestor is
what the library will use by default), then you can explicitly set the
`scrollableAncestor` to be the `window` to ensure that no other element is used.
This might look something like:
```jsx
```
## Troubleshooting
If your waypoint isn't working the way you expect it to, there are a few ways
you can debug your setup.
OPTION 1: Add the `debug={true}` prop to your waypoint. When you do, you'll see console
logs informing you about the internals of the waypoint.
OPTION 2: Clone and modify the project locally.
- clone this repo
- add `console.log` or breakpoints where you think it would be useful.
- `npm link` in the react-waypoint repo.
- `npm link react-waypoint` in your project.
- if needed rebuild react-waypoint module: `npm run build-npm`
## Limitations
In this component we make a few assumptions that we believe are generally safe,
but in some situations might present limitations.
- We determine the scrollable-ness of a node by inspecting its computed
overflow-y or overflow property and nothing else. This could mean that a
container with this style that does not actually currently scroll will be
considered when performing visibility calculations.
- We assume that waypoints are rendered within at most one scrollable container.
If you render a waypoint in multiple nested scrollable containers, the
visibility calculations will likely not be accurate.
- We also base the visibility calculations on the scroll position of the
scrollable container (or `window` if no scrollable container is found). This
means that if your scrollable container has a height that is greater than the
window, it might trigger `onEnter` unexpectedly.
## In the wild
[Organizations and projects using `react-waypoint`](INTHEWILD.md).
## Credits
Credit to [trotzig][trotzig-github] and [lencioni][lencioni-github] for writing
this component, and [Brigade][brigade-home] for open sourcing it.
Thanks to the creator of the original Waypoints library,
[imakewebthings][imakewebthings-github].
[lencioni-github]: https://github.com/lencioni
[trotzig-github]: https://github.com/trotzig
[brigade-home]: https://www.brigade.com/
[imakewebthings-github]: https://github.com/imakewebthings
## License
[MIT][mit-license]
[mit-license]: ./LICENSE
---
_Make sure to check out other popular open-source tools from the
[Brigade][civiccc-github] team: [dock], [overcommit], [haml-lint], and [scss-lint]._
[civiccc-github]: https://github.com/civiccc
[dock]: https://github.com/civiccc/dock
[overcommit]: https://github.com/sds/overcommit
[haml-lint]: https://github.com/sds/haml-lint
[scss-lint]: https://github.com/sds/scss-lint