Skip to content

Commit

Permalink
Merge pull request #76 from jedwards1211/children-function
Browse files Browse the repository at this point in the history
allow passing a children function that takes state and chooses what to render from it
  • Loading branch information
joshwnj authored Jun 7, 2017
2 parents 28f5301 + 9b8c306 commit 9c11db6
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 3 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,17 @@ function render () {
}
```

You can also pass a child function, which can be convenient if you don't need to store the visibility anywhere:

```js
return (
<VisibilitySensor>
{({isVisible}) =>
<div>I am {isVisible ? 'visible' : 'invisible'}</div>
}
</VisibilitySensor>
);
```

Props
----
Expand All @@ -66,6 +77,7 @@ Props
- `resizeThrottle`: (default: `-1`) by specifying a value > -1, you are enabling throttle instead of the delay to trigger checks on resize event. Throttle supercedes delay.
- `containment`: (optional) element to use as a viewport when checking visibility. Default behaviour is to use the browser window as viewport.
- `delayedCall`: (default `false`) if is set to true, wont execute on page load ( prevents react apps triggering elements as visible before styles are loaded )
- `children`: can be a React element or a function. If you provide a function, it will be called with 1 argument `{isVisible: ?boolean, visibilityRect: Object}`

It's possible to use both `intervalCheck` and `scrollCheck` together. This means you can detect most visibility changes quickly with `scrollCheck`, and an `intervalCheck` with a higher `intervalDelay` will act as a fallback for other visibility events, such as resize of a container.

Expand Down
20 changes: 20 additions & 0 deletions tests/visibility-sensor-spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -241,4 +241,24 @@ describe('VisibilitySensor', function () {
ReactDOM.render(element, node);
});

it('should call child function with state', function (done) {
var wasChildrenCalled = false;
var children = function (props) {
wasChildrenCalled = true;
assert('isVisible' in props, 'children should be called with isVisible prop');
assert('visibilityRect' in props, 'children should be called with visibilityRect prop');
return <div />;
};

setTimeout(function () {
assert(wasChildrenCalled, 'children should be called');
done();
}, 200);

var element = (
<VisibilitySensor>{children}</VisibilitySensor>
);

ReactDOM.render(element, node);
});
});
15 changes: 12 additions & 3 deletions visibility-sensor.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ module.exports = createReactClass({
displayName: 'VisibilitySensor',

propTypes: {
onChange: PropTypes.func.isRequired,
onChange: PropTypes.func,
active: PropTypes.bool,
partialVisibility: PropTypes.oneOfType([
PropTypes.bool,
Expand Down Expand Up @@ -71,7 +71,10 @@ module.exports = createReactClass({
intervalCheck: PropTypes.bool,
intervalDelay: PropTypes.number,
containment: containmentPropType,
children: PropTypes.element,
children: PropTypes.oneOfType([
PropTypes.element,
PropTypes.func,
]),
minTopValue: PropTypes.number,
},

Expand Down Expand Up @@ -303,13 +306,19 @@ module.exports = createReactClass({
visibilityRect: visibilityRect
};
this.setState(state);
this.props.onChange(isVisible, visibilityRect);
if (this.props.onChange) this.props.onChange(isVisible, visibilityRect);
}

return state;
},

render: function () {
if (this.props.children instanceof Function) {
return this.props.children({
isVisible: this.state.isVisible,
visibilityRect: this.state.visibilityRect,
});
}
return React.Children.only(this.props.children);
}
});

0 comments on commit 9c11db6

Please sign in to comment.