Monday, June 3, 2024
 Popular · Latest · Hot · Upcoming
96
rated 0 times [  100] [ 4]  / answers: 1 / hits: 113953  / 9 Years ago, thu, october 1, 2015, 12:00:00

I am animating several React.js components based on their position in the viewport. If the component is in the viewport, animate the opacity to 1, if it's not in the viewport, animate its opacity to 0. I am using getBoundingClient()'s top and bottom properties to determine if the component is within the viewport.



ComponentA shows the pattern I followed for the other B, C, and D components. They each are listening for the window scroll event.



Is this the React way to do this by each component having its having to add an event listener to the window? Multiple scroll event listeners on the same window?



Or is there a better way by adding the scroll event listener to the window once at the Home owner component? Then would the ownee child components still be able to know where they are in the DOM using the getBoundingClient()?



Home = React.createClass({
render: function() {
<div>
<ComponentA />
<ComponentB />
<ComponentC />
<ComponentD />
</div>
};
});

ComponentA = React.createClass({
componentDidMount: function() {
window.addEventListener('scroll', this.handleScroll);
},
componentWillUnmount: function() {
window.removeEventListener('scroll', this.handleScroll);
},

handleScroll: function() {
var domElement = this.refs.domElement.getDOMNode();
this.inViewPort(domElement);
},

inViewPort: function(element) {
var elementBounds = element.getBoundingClientRect();
(elementBounds.top <= 769 && elementBounds.bottom >= 430) ? TweenMax.to(element, 1.5, { opacity: 1 }) : TweenMax.to(element, 1.5, { opacity: 0 });
},
render: function() {
return (/* html to render */);
}

});

More From » reactjs

 Answers
24

There are a few different ways you could do this. One is through composition:



var React = require(react);
var _ = require(underscore);

var ScrollWrapper = React.createClass({
propTypes: {
onWindowScroll: React.PropTypes.func
},

handleScroll: function(event) {
// Do something generic, if you have to
console.log(ScrollWrapper's handleScroll);

// Call the passed-in prop
if (this.props.onWindowScroll) this.props.onWindowScroll(event);
},

render: function () {
return this.props.children;
},

componentDidMount: function() {
if (this.props.onWindowScroll) window.addEventListener(scroll, this.handleScroll);
},

componentWillUnmount: function() {
if (this.props.onWindowScroll) window.removeEventListener(scroll, this.handleScroll);
}
});

var ComponentA = React.createClass({
handleScroll: function(event) {
console.log(ComponentA's handleScroll);
},

render: function() {
return (
<ScrollWrapper onWindowScroll={this.handleScroll}>
<div>whatever</div>
</ScrollWrapper>
);
}
});


Now, you can place your generic logic in the ScrollWrapper component, and suddenly it becomes reusable. You could create a ComponentB that renders a ScrollWrapper just like ComponentA does.



To satisfy your example, maybe you'll have to pass the ScrollWrapper some extra props from ComponentA. Maybe you'll pass it a prop that contains an instance of the ref to call your logic on. You could even pass it some options or arguments to customize the tween or the bounds. I didn't code any of this because I think you'll understand it and be able to customize/write it for yourself with the base I've provided.



The other way to achieve this sort of thing is through a Mixin. Although, there's a lot of talk about if Mixins are good or bad, and they might even be being deprecated by React in the future? You can do some reading about this and decide for yourself what you think.


[#64868] Tuesday, September 29, 2015, 9 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
margaritakristinak

Total Points: 502
Total Questions: 127
Total Answers: 98

Location: England
Member since Mon, May 17, 2021
3 Years ago
;