Skip to content

Commit 4d3ddcb

Browse files
committed
feat(improve-perf): Implementing id prefix in focusIndex
1 parent b060134 commit 4d3ddcb

File tree

4 files changed

+39
-30
lines changed

4 files changed

+39
-30
lines changed

src/@types/index.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ export interface IFocusOnScrollProps {
88
children: ChildrenArray;
99
className?: string;
1010
focusOn?: string;
11-
onFocus?: (focusIndex: number) => void;
11+
onFocus?: () => void;
1212
}
1313

1414
export interface IFocusOnScrollState {
15-
focusIndex: number;
15+
focusIndex: string;
1616
}
1717

1818
export type ChildrenArray = any[];

src/components/FocusOnScroll.tsx

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
} from '../helpers/config';
77
import {
88
findFocusElement,
9+
getFocusIndex,
910
throttle,
1011
debounce,
1112
} from '../helpers/utils';
@@ -22,7 +23,7 @@ class FocusOnScroll extends React.Component<IFocusOnScrollProps, IFocusOnScrollS
2223
constructor(props: IFocusOnScrollProps) {
2324
super(props);
2425
this.state = {
25-
focusIndex: Number(this.props.focusOn) || 0,
26+
focusIndex: getFocusIndex(this.props.focusOn),
2627
};
2728
}
2829
private debounceResizeHandler = () => debounce(this.scrollHandler, DELAY_TIME_IN_MS);
@@ -44,27 +45,25 @@ class FocusOnScroll extends React.Component<IFocusOnScrollProps, IFocusOnScrollS
4445

4546
public componentDidUpdate(prevProps: IFocusOnScrollProps) {
4647
if (this.props.focusOn !== prevProps.focusOn) {
47-
this.focusOnHandler(prevProps.focusOn!);
48+
this.focusOnHandler(getFocusIndex(prevProps.focusOn));
4849
}
4950
}
5051

5152
public componentWillUnmount() {
52-
console.log('will unmout');
5353
window.removeEventListener('scroll', this.throttleScrollHandler);
5454
window.removeEventListener('resize', this.debounceResizeHandler);
5555
this.debounceResizeHandlerRef.cancel();
5656
this.throttleScrollHandlerRef.cancel();
5757
}
5858

59-
public focusOnHandler = (index: string): void => {
60-
const sections = Array.prototype.slice.call(document.getElementsByClassName('rfs-section'));
61-
const focusIndex = Number(index);
62-
if (isNaN(focusIndex) || focusIndex >= sections.length) {
63-
return ;
59+
public focusOnHandler = (focusIndex: string): void => {
60+
const focusElement = document.getElementById(focusIndex);
61+
if (!focusElement) {
62+
return;
6463
}
65-
const { height } = sections[focusIndex].getBoundingClientRect();
66-
const scrollPosition = (sections[focusIndex] as any).offsetTop + height / 2 - window.innerHeight / 2;
67-
window.scrollTo(0, scrollPosition + 1);
64+
const { height } = focusElement.getBoundingClientRect();
65+
const scrollPosition = focusElement.offsetTop + height / 2 - window.innerHeight / 2;
66+
window.scrollTo(0, scrollPosition - 1);
6867
this.setFocusIndex(focusIndex);
6968
}
7069

@@ -83,27 +82,26 @@ class FocusOnScroll extends React.Component<IFocusOnScrollProps, IFocusOnScrollS
8382
const { focusIndex } = this.state;
8483
const childElement = event.target;
8584
const selectedSection = childElement.closest('section');
86-
const str = selectedSection.id.split('-');
87-
const id = str[str.length - 1];
88-
const alreadyInFocusArea = focusIndex === id;
85+
86+
const alreadyInFocusArea = focusIndex === selectedSection.id;
8987
if (!alreadyInFocusArea) {
90-
this.focusOnHandler(id);
88+
this.focusOnHandler(selectedSection.id);
9189
}
9290
}
9391

9492
public scrollHandler = (): void => {
9593
const focusIndex = findFocusElement();
96-
if (focusIndex >= 0) {
94+
if (focusIndex) {
9795
this.setFocusIndex(focusIndex);
9896
}
9997
}
10098

101-
public setFocusIndex = (focusIndex: number): void => {
99+
public setFocusIndex = (focusIndex: string): void => {
102100
if (this.state.focusIndex !== focusIndex) {
103101
const { onFocus } = this.props;
104102
this.setState({ focusIndex });
105103
if (typeof onFocus === 'function') {
106-
onFocus(focusIndex);
104+
onFocus();
107105
}
108106
}
109107
}
@@ -112,9 +110,9 @@ class FocusOnScroll extends React.Component<IFocusOnScrollProps, IFocusOnScrollS
112110
const { children } = this.props;
113111

114112
return React.Children.map(children, (element, index) => {
115-
const focused = this.state.focusIndex === index;
113+
const id = getFocusIndex(index);
114+
const focused = this.state.focusIndex === id;
116115
const focusedClassName = focused ? 'focused' : '';
117-
const id = `rfs-section-${index}`;
118116

119117
return (
120118
<section

src/helpers/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export const DELAY_TIME_IN_MS = 250;
22
export const SUPPORTED_TAGS_FOR_FOCUS: string[] = ['input', 'label', 'select'];
3+
export const ID_PREFIX = 'rfs-section-';

src/helpers/utils.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,31 @@
1+
import {
2+
ID_PREFIX,
3+
} from './config';
4+
15
export const findFocusElement = () => {
26
const sectionNodes = document.getElementsByClassName('rfs-section');
37
const sections = Array.prototype.slice.call(sectionNodes);
48
const totalHeight = document.body.offsetHeight - window.innerHeight;
59
if (sections.length === 0) {
6-
return -1;
10+
return '';
711
}
812
if (window.scrollY === 0) {
9-
return 0;
13+
return getFocusIndex(0);
1014
}
1115
if (window.scrollY >= totalHeight) {
12-
return sections.length - 1;
16+
return getFocusIndex(sections.length - 1);
1317
}
1418

1519
const focusPoint = window.innerHeight / 2;
1620

17-
for (let i = 0 ; i < sections.length; i++) {
18-
const top = sections[i].getBoundingClientRect().top;
19-
const bottom = top + sections[i].getBoundingClientRect().height;
21+
for (const section of sections) {
22+
const top = section.getBoundingClientRect().top;
23+
const bottom = top + section.getBoundingClientRect().height;
2024
if (!(top > focusPoint || bottom < focusPoint)) {
21-
return i;
25+
return section.id;
2226
}
2327
}
24-
return -1;
28+
return '';
2529
};
2630

2731
export const debounce = (fn: any, wait: number) => {
@@ -72,3 +76,9 @@ export const throttle = (fn: any, wait: number) => {
7276
};
7377
return resolver;
7478
};
79+
80+
export const getFocusIndex = (index: string | number | undefined): string => {
81+
const id = Number(index) || 0;
82+
const focusIndex = `${ID_PREFIX}${id}`;
83+
return focusIndex;
84+
};

0 commit comments

Comments
 (0)