react-native-intersection-observer
Version:
react native intersection observer
107 lines (106 loc) • 3.77 kB
JavaScript
import React, { PureComponent, createRef, } from 'react';
import IOContext from './IOContext';
import IOManager from './IOManager';
function withIO(Comp, methods) {
const IOScrollableComponent = class extends PureComponent {
node;
scroller;
root;
manager;
contextValue;
constructor(props) {
super(props);
const self = this;
this.scroller = createRef();
this.root = {
get node() {
return self.node;
},
get horizontal() {
return !!self.props.horizontal;
},
current: {
contentInset: {
top: 0,
right: 0,
bottom: 0,
left: 0,
},
contentOffset: {
x: 0,
y: 0,
},
contentSize: {
width: 0,
height: 0,
},
layoutMeasurement: {
width: 0,
height: 0,
},
zoomScale: 1,
},
};
const manager = new IOManager({
root: this.root,
get rootMargin() {
return self.props.rootMargin;
},
});
this.manager = manager;
this.contextValue = {
manager,
};
}
componentDidMount() {
this.node =
this.scroller.current?.getNativeScrollRef?.() || this.scroller.current;
methods.forEach((method) => {
this[method] = (...args) => {
this.scroller.current?.[method]?.(...args);
};
});
}
handleContentSizeChange = (width, height) => {
const { contentSize } = this.root.current;
if (width !== contentSize.width || height !== contentSize.height) {
this.root.current.contentSize = { width, height };
if (width > 0 && height > 0 && this.root.onLayout) {
this.root.onLayout();
}
}
const { onContentSizeChange } = this.props;
if (onContentSizeChange) {
onContentSizeChange(width, height);
}
};
handleLayout = (event) => {
const { nativeEvent: { layout }, } = event;
const { layoutMeasurement } = this.root.current;
if (layoutMeasurement.width !== layout.width ||
layoutMeasurement.height !== layout.height) {
this.root.current.layoutMeasurement = layout;
}
const { onLayout } = this.props;
if (onLayout) {
onLayout(event);
}
};
handleScroll = (event) => {
this.root.current = event.nativeEvent;
if (this.root.onScroll) {
this.root.onScroll(this.root.current);
}
const { onScroll } = this.props;
if (onScroll) {
onScroll(event);
}
};
render() {
return (React.createElement(IOContext.Provider, { value: this.contextValue },
React.createElement(Comp, { scrollEventThrottle: 16, ...this.props, ref: this.scroller, onContentSizeChange: this.handleContentSizeChange, onLayout: this.handleLayout, onScroll: this.handleScroll })));
}
};
return IOScrollableComponent;
}
export default withIO;