Reputation: 417
I have a react component that has a sub component slider. I have synched up the components such that the parent components state tracks the scroll position and passes that as a prop to the slider to trigger a re render with the new value as the slider position.
export default class ParentComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
scrollPosition: 0
};
}
render() {
return (
<div id="container" onScroll={this.updateScroll}>
<Slider
max={'2000px'}
value={this.state.scrollPosition}
onChange={(value) =>
ReactDom.findDOMNode(this).firstChild.scrollTo(value, 0);}}
showValue={false}
/>
</div>
);
}
updateScroll = (e) => {
const container = e.target;
this.setState(function(state, props){
return {scrollPosition: container.scrollLeft};
});
}
}
Under onchange, I find the dom element and update the scroll value, which will not trigger a re-render.
However I could also call the updateScroll function, to set the state to the new value of the Slider and then trigger a re-render through the React lifecycle. This however I feel like is not as good performance wise as simply updating the property of a dom element and not re-rendering everything.
Given that we could use refs as well and not perform a dom search for the element to update, which approach is best practice and adheres the most to the React standards? Is there an entirely better way to implement this interaction?
Thanks in advance for your help!
Upvotes: 0
Views: 2462
Reputation: 5442
Hope I understand correctly and you wish to present the scroll position. Indeed setting state for every scroll update is bad performance. Scroll events could trigger at a higher rate than the frames you need to update.
To ease the amount of updates you perform, you can use a debounced method. Here's a short implementation of debounce. It will limit the amount of scroll updates you will perform per a given time.
export default class ParentComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
scrollPosition: 0
};
this.updateScroll = debounce(this.updateScroll, 20);
}
...
}
Upvotes: 1