).';
- // Because of how we detect when a Waypoint is scrolled past without any
- // scroll event fired when it was visible, we need to reset callback
- // spies.
- scrollNodeTo(this.scrollable, 400);
- this.props.onEnter.calls.reset();
- this.props.onLeave.calls.reset();
- scrollNodeTo(this.scrollable, 400);
- });
+ it('errors with a stateless component', () => {
+ const StatelessComponent = () => React.createElement('div');
+ this.props.children = React.createElement(StatelessComponent);
- it('does not call the onEnter handler', () => {
- expect(this.props.onEnter).not.toHaveBeenCalled();
+ expect(this.subject).toThrowError(errorMessage);
});
- it('does not call the onLeave handler', () => {
- expect(this.props.onLeave).not.toHaveBeenCalled();
- });
-
- describe('when scrolled back up just past the bottom', () => {
- beforeEach(() => {
- scrollNodeTo(this.scrollable, this.topSpacerHeight + 50);
- });
-
- it('calls the onEnter handler', () => {
- expect(this.props.onEnter).
- toHaveBeenCalledWith({
- currentPosition: Waypoint.inside,
- previousPosition: Waypoint.above,
- event: jasmine.any(Event),
- waypointTop: -40,
- waypointBottom: -40 + this.childrenHeight,
- viewportTop: this.margin,
- viewportBottom: this.margin + this.parentHeight,
- });
- });
+ it('errors with a class-based component', () => {
+ class ClassBasedComponent extends React.Component {
+ render() {
+ return React.createElement('div');
+ }
+ }
+ this.props.children = React.createElement(ClassBasedComponent);
- it('does not call the onLeave handler', () => {
- expect(this.props.onLeave).not.toHaveBeenCalled();
- });
+ expect(this.subject).toThrowError(errorMessage);
});
});
- describe('when noWrapper=true and child is above the top', () => {
+ describe('when the Waypoint has children and is above the top', () => {
beforeEach(() => {
this.topSpacerHeight = 200;
this.bottomSpacerHeight = 200;
this.childrenHeight = 100;
- this.childRefSpy = jasmine.createSpy('ref');
- this.props.noWrapper = true;
- this.props.children = React.createElement('section', {
- ref: this.childRefSpy,
+ this.props.children = React.createElement('div', {
style: {
height: this.childrenHeight,
}
@@ -930,14 +898,6 @@ describe('
', function() {
scrollNodeTo(this.scrollable, 400);
});
- it('calls the original ref handler', () => {
- expect(this.childRefSpy).toHaveBeenCalled();
- });
-
- it('does not have an extra div', () => {
- expect(this.scrollable.children[1].nodeName).toBe('SECTION');
- });
-
it('does not call the onEnter handler', () => {
expect(this.props.onEnter).not.toHaveBeenCalled();
});
diff --git a/src/waypoint.jsx b/src/waypoint.jsx
index 7628f8e..994fcba 100644
--- a/src/waypoint.jsx
+++ b/src/waypoint.jsx
@@ -120,6 +120,13 @@ function computeOffsetPixels(offset, contextHeight) {
}
}
+/**
+ * @param {React.element} Component
+ * @return {bool} Whether the component is a DOM Element
+ */
+function isDomElement(Component) {
+ return (typeof Component.type === 'string');
+}
/**
* Calls a function when you scroll to the element.
@@ -352,8 +359,13 @@ export default class Waypoint extends React.Component {
* @return {Object}
*/
render() {
- if (this.props.noWrapper) {
+ if (this.props.children) {
const child = React.Children.only(this.props.children);
+ if (!isDomElement(child)) {
+ throw new Error(
+ 'You must wrap any Component Elements passed to Waypoint in a DOM Element (eg; a ).'
+ );
+ }
const ref = (node) => {
this.refElement(node);
if (this.props.children.ref) {
@@ -363,10 +375,6 @@ export default class Waypoint extends React.Component {
return React.cloneElement(child, { ref });
}
- if (this.props.children) {
- return
{this.props.children}
;
- }
-
// We need an element that we can locate in the DOM to determine where it is
// rendered relative to the top of its context.
return
;
@@ -374,8 +382,7 @@ export default class Waypoint extends React.Component {
}
Waypoint.propTypes = {
- children: PropTypes.node,
- noWrapper: PropTypes.bool,
+ children: PropTypes.element,
debug: PropTypes.bool,
onEnter: PropTypes.func,
onLeave: PropTypes.func,