Skip to content

Commit d0167f1

Browse files
committed
fix(StickyPlaceholder): do not recalculate placeholder rect on scroll
The Placeholder component did update and therefore recalculates rects every time when a Sticky/ StickyScrollUp component was rerendered and therefore forces layout which results in bad performance. With this fix the component will still rerender on an update but will not force layouts anymore.
1 parent 58e082a commit d0167f1

File tree

3 files changed

+61
-54
lines changed

3 files changed

+61
-54
lines changed

lib/Sticky.tsx

+24-26
Original file line numberDiff line numberDiff line change
@@ -148,15 +148,30 @@ class Sticky extends React.PureComponent<IProps, IState> {
148148
});
149149
};
150150

151+
renderSticky = ({ isRecalculating }) => {
152+
const { children, disabled, stickyProps } = this.props;
153+
return (
154+
<StickyElement<
155+
TRenderChildren<{
156+
isSticky: boolean;
157+
isDockedToBottom: boolean;
158+
}>
159+
>
160+
forwardRef={this.stickyRef}
161+
positionStyle={this.state.styles}
162+
disabled={disabled || isRecalculating}
163+
children={children}
164+
renderArgs={{
165+
isSticky: this.state.isSticky,
166+
isDockedToBottom: this.state.isDockedToBottom,
167+
}}
168+
{...stickyProps}
169+
/>
170+
);
171+
};
172+
151173
render() {
152-
const {
153-
children,
154-
disabled,
155-
disableResizing,
156-
stickyProps,
157-
style,
158-
className,
159-
} = this.props;
174+
const { disabled, disableResizing, style, className } = this.props;
160175
return (
161176
<>
162177
<StickyPlaceholder
@@ -167,24 +182,7 @@ class Sticky extends React.PureComponent<IProps, IState> {
167182
stickyRef={this.stickyRef}
168183
disableResizing={disableResizing}
169184
>
170-
{({ isRecalculating }) => (
171-
<StickyElement<
172-
TRenderChildren<{
173-
isSticky: boolean;
174-
isDockedToBottom: boolean;
175-
}>
176-
>
177-
forwardRef={this.stickyRef}
178-
positionStyle={this.state.styles}
179-
disabled={disabled || isRecalculating}
180-
children={children}
181-
renderArgs={{
182-
isSticky: this.state.isSticky,
183-
isDockedToBottom: this.state.isDockedToBottom,
184-
}}
185-
{...stickyProps}
186-
/>
187-
)}
185+
{this.renderSticky}
188186
</StickyPlaceholder>
189187
<ObserveViewport
190188
disableDimensionsUpdates

lib/StickyPlaceholder.tsx

+22-11
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ interface IState {
2323
clientSize: string | null;
2424
}
2525

26-
class StickyPlaceholder extends React.PureComponent<IProps, IState> {
26+
class StickyPlaceholder extends React.Component<IProps, IState> {
2727
static defaultProps = {
2828
style: {},
2929
};
@@ -43,25 +43,36 @@ class StickyPlaceholder extends React.PureComponent<IProps, IState> {
4343
}
4444
}
4545

46-
static getDerivedStateFromProps(props: IProps, state: IState): IState {
46+
static getDerivedStateFromProps(props: IProps, state: IState): IState | null {
47+
const nextClientSize = `${props.dimensions.width}`;
48+
if (state.isRecalculating) {
49+
const stickyRect = props.stickyRef.current.getBoundingClientRect();
50+
return {
51+
stickyHeight: stickyRect.height,
52+
stickyWidth: stickyRect.width,
53+
clientSize: nextClientSize,
54+
isRecalculating: false,
55+
};
56+
}
57+
4758
if (!props.stickyRef.current) {
4859
return {
4960
...state,
5061
isRecalculating: true,
5162
};
5263
}
5364

54-
const stickyRect = props.stickyRef.current.getBoundingClientRect();
55-
const nextClientSize = `${props.dimensions.width}`;
56-
const shouldRecalculate =
65+
const triggerRecalculation =
5766
!props.disableResizing && state.clientSize !== nextClientSize;
5867

59-
return {
60-
stickyHeight: stickyRect.height,
61-
stickyWidth: stickyRect.width,
62-
clientSize: nextClientSize,
63-
isRecalculating: shouldRecalculate,
64-
};
68+
if (triggerRecalculation) {
69+
return {
70+
...state,
71+
isRecalculating: true,
72+
};
73+
}
74+
75+
return null;
6576
}
6677

6778
render() {

lib/StickyScrollUp.tsx

+15-17
Original file line numberDiff line numberDiff line change
@@ -132,15 +132,21 @@ class StickyScrollUp extends React.PureComponent<IProps, IState> {
132132
});
133133
};
134134

135+
renderSticky = ({ isRecalculating }) => {
136+
const { disabled, children, stickyProps } = this.props;
137+
return (
138+
<StickyElement<TRenderChildren<undefined>>
139+
forwardRef={this.stickyRef}
140+
positionStyle={this.state.styles}
141+
disabled={disabled || isRecalculating}
142+
children={children}
143+
{...stickyProps}
144+
/>
145+
);
146+
};
147+
135148
render() {
136-
const {
137-
children,
138-
disabled,
139-
disableResizing,
140-
stickyProps,
141-
style,
142-
className,
143-
} = this.props;
149+
const { disabled, disableResizing, style, className } = this.props;
144150
return (
145151
<>
146152
<StickyPlaceholder
@@ -150,15 +156,7 @@ class StickyScrollUp extends React.PureComponent<IProps, IState> {
150156
stickyRef={this.stickyRef}
151157
disableResizing={disableResizing}
152158
>
153-
{({ isRecalculating }) => (
154-
<StickyElement<TRenderChildren<undefined>>
155-
forwardRef={this.stickyRef}
156-
positionStyle={this.state.styles}
157-
disabled={disabled || isRecalculating}
158-
children={children}
159-
{...stickyProps}
160-
/>
161-
)}
159+
{this.renderSticky}
162160
</StickyPlaceholder>
163161
<ObserveViewport
164162
disableDimensionsUpdates

0 commit comments

Comments
 (0)