Skip to content

Commit

Permalink
No markRefs unless renderMarks is provided
Browse files Browse the repository at this point in the history
We have an application that uses react-range under the hood, and we
noticed that a range input was taking 2GB of RAM on our machines. I did
some investigation and found that regardless of whether the marks
functionality was being used, refs were being created for each possible
value of the range.

We have some fairly huge ranges (we're using the input to scrub a video
with potential microsecond accuracy), and can imagine that other people
are affected by the previous behavior. This change should allow us to
continue using large input ranges without incurring a memory penalty.
  • Loading branch information
wolfd committed Jul 15, 2022
1 parent 34b6dcf commit 8eca42e
Showing 1 changed file with 20 additions and 12 deletions.
32 changes: 20 additions & 12 deletions src/Range.tsx
Expand Up @@ -34,8 +34,8 @@ class Range extends React.Component<IProps> {
};
trackRef = React.createRef<HTMLElement>();
thumbRefs: React.RefObject<HTMLElement>[] = [];
markRefs: React.RefObject<HTMLElement>[] = [];
numOfMarks: number;
markRefs?: React.RefObject<HTMLElement>[];
numOfMarks?: number;
resizeObserver: any;
schdOnMouseMove: (e: MouseEvent) => void;
schdOnTouchMove: (e: TouchEvent) => void;
Expand All @@ -54,14 +54,11 @@ class Range extends React.Component<IProps> {
throw new Error('"step" property should be a positive number');
}

this.numOfMarks = (props.max - props.min) / this.props.step;
this.schdOnMouseMove = schd(this.onMouseMove);
this.schdOnTouchMove = schd(this.onTouchMove);
this.schdOnEnd = schd(this.onEnd);
this.thumbRefs = props.values.map(() => React.createRef<HTMLElement>());
for (let i = 0; i < this.numOfMarks + 1; i++) {
this.markRefs[i] = React.createRef<HTMLElement>();
}
this.updateMarkRefs(props);
}

componentDidMount() {
Expand Down Expand Up @@ -103,11 +100,7 @@ class Range extends React.Component<IProps> {
prevProps.min !== min ||
prevProps.step !== step
) {
this.markRefs = [];
this.numOfMarks = (max - min) / step;
for (let i = 0; i < this.numOfMarks + 1; i++) {
this.markRefs[i] = React.createRef<HTMLElement>();
}
this.updateMarkRefs(this.props);
}
translateThumbs(this.getThumbs(), this.getOffsets(), rtl);
// ensure offsets are calculated when the refs for the marks have been created
Expand Down Expand Up @@ -557,10 +550,25 @@ class Range extends React.Component<IProps> {
}
};

updateMarkRefs = (props: IProps) => {
if (!props.renderMark) { // don't create mark refs unless we are rendering marks
this.numOfMarks = undefined;
this.markRefs = undefined;
return;
}
this.numOfMarks = (props.max - props.min) / this.props.step;
this.markRefs = [];
for (let i = 0; i < this.numOfMarks + 1; i++) {
this.markRefs[i] = React.createRef<HTMLElement>();
}
}

calculateMarkOffsets = () => {
if (
!this.props.renderMark ||
!this.trackRef ||
!this.numOfMarks ||
!this.markRefs ||
this.trackRef.current === null
)
return;
Expand Down Expand Up @@ -657,7 +665,7 @@ class Range extends React.Component<IProps> {
marginLeft: `${offset[1]}px`
},
key: `mark${index}`,
ref: this.markRefs[index]
ref: this.markRefs![index]
},
index
})
Expand Down

0 comments on commit 8eca42e

Please sign in to comment.