From 384b1672d23019a9908e01340260fc12e60c1c89 Mon Sep 17 00:00:00 2001 From: Maxim Malov <m.malov.v@gmail.com> Date: Fri, 8 Jun 2018 22:31:27 +0600 Subject: [PATCH 1/2] Introduce children function support --- README.md | 30 +++++++++++++++++++++++++++--- src/Sticky.jsx | 4 +++- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index cee13aa6..c89d953c 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ import Sticky from 'react-stickynode'; ### Handling State Change -You can be notified when the state of the sticky component changes by passing a callback to the `onStateChange` prop. The callback will receive an object in the format `{status: CURRENT_STATUS}`, with `CURRENT_STATUS` being an integer representing the status: +You can be notified when the state of the sticky component changes by passing a callback to the `onStateChange` prop. The callback will receive an object in the format `{status: CURRENT_STATUS}`, with `CURRENT_STATUS` being an integer representing the status: - 0 (STATUS_ORIGINAL) - The default status, located at the original position. - 1 (STATUS_RELEASED) - The released status, located at somewhere on document, but not default one. @@ -81,9 +81,33 @@ const handleStateChange = (status) => { </Sticky> ``` -### Freezing +Also `Sticky` supports children functions: -You can provide a function in the `shouldFreeze` prop which will tell the component to temporarily stop updating during prop and state changes, as well as ignore scroll and resize events. This function should return a boolean indicating whether the component should currently be frozen. +```js +import Sticky from 'react-stickynode'; + +const handleStateChange = (status) => { + if (status.status === Sticky.STATUS_FIXED) { + console.log('the component is sticky'); + } +} + +<Sticky> + {status => { + if (status.status === Sticky.STATUS_FIXED) { + return 'the component is sticky'; + } + if (status.status === Sticky.STATUS_ORIGINAL) { + return 'the component in the original position'; + } + return 'the component is released' + }} +</Sticky> +``` + +### Freezing + +You can provide a function in the `shouldFreeze` prop which will tell the component to temporarily stop updating during prop and state changes, as well as ignore scroll and resize events. This function should return a boolean indicating whether the component should currently be frozen. ## Install & Development diff --git a/src/Sticky.jsx b/src/Sticky.jsx index 49b7d172..fe7e494e 100644 --- a/src/Sticky.jsx +++ b/src/Sticky.jsx @@ -380,10 +380,12 @@ class Sticky extends Component { [this.props.releasedClass]: this.state.status === STATUS_RELEASED }) + var children = this.props.children; + return ( <div ref={(outer) => { this.outerElement = outer; }} className={outerClasses} style={outerStyle}> <div ref={(inner) => { this.innerElement = inner; }} className='sticky-inner-wrapper' style={innerStyle}> - {this.props.children} + {typeof children === 'function' ? children({ status: this.state.status }) : children} </div> </div> ); From ffbaea4e0680c4706c8d93c803fbacd79846491f Mon Sep 17 00:00:00 2001 From: Maxim Malov <m.malov.v@gmail.com> Date: Tue, 30 Oct 2018 11:19:51 +0600 Subject: [PATCH 2/2] Add test to cover children function is working the same way as `onStateChange` --- README.md | 6 ------ tests/unit/Sticky-test.js | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index c89d953c..e6480592 100644 --- a/README.md +++ b/README.md @@ -86,12 +86,6 @@ Also `Sticky` supports children functions: ```js import Sticky from 'react-stickynode'; -const handleStateChange = (status) => { - if (status.status === Sticky.STATUS_FIXED) { - console.log('the component is sticky'); - } -} - <Sticky> {status => { if (status.status === Sticky.STATUS_FIXED) { diff --git a/tests/unit/Sticky-test.js b/tests/unit/Sticky-test.js index b4686c6c..67bfa7b5 100644 --- a/tests/unit/Sticky-test.js +++ b/tests/unit/Sticky-test.js @@ -171,6 +171,22 @@ describe('Sticky', function () { sinon.assert.calledWith(callback.secondCall, {status: Sticky.STATUS_ORIGINAL}); }); + it('should call the children function on state change', function () { + var childrenStub = sinon.stub().returns(null); + jsx.renderComponent(Sticky, { children: childrenStub }); + + sinon.assert.notCalled(childrenStub); + + // Scroll down to 10px, and status should change to FIXED + window.scrollTo(0, 10); + sinon.assert.calledWith(childrenStub, {status: Sticky.STATUS_FIXED}); + + // Scroll up to 0px, and Sticky should reset + window.scrollTo(0, 0); + sinon.assert.calledTwice(childrenStub); + sinon.assert.calledWith(childrenStub.secondCall, {status: Sticky.STATUS_ORIGINAL}); + }); + it('should work as expected (long Sticky)', function () { STICKY_HEIGHT = 1200; sticky = jsx.renderComponent(Sticky);