diff --git a/src/components/OptionsListSkeletonView.js b/src/components/OptionsListSkeletonView.js
deleted file mode 100644
index 2c46ac5d4d7a..000000000000
--- a/src/components/OptionsListSkeletonView.js
+++ /dev/null
@@ -1,114 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import {View} from 'react-native';
-import {Circle, Rect} from 'react-native-svg';
-import compose from '@libs/compose';
-import CONST from '@src/CONST';
-import SkeletonViewContentLoader from './SkeletonViewContentLoader';
-import withTheme, {withThemePropTypes} from './withTheme';
-import withThemeStyles, {withThemeStylesPropTypes} from './withThemeStyles';
-
-const propTypes = {
- /** Whether to animate the skeleton view */
- shouldAnimate: PropTypes.bool,
- ...withThemeStylesPropTypes,
- ...withThemePropTypes,
-};
-
-const defaultTypes = {
- shouldAnimate: true,
-};
-
-class OptionsListSkeletonView extends React.Component {
- constructor(props) {
- super(props);
- this.state = {
- skeletonViewItems: [],
- };
- }
-
- /**
- * Generate the skeleton view items.
- *
- * @param {Number} numItems
- */
- generateSkeletonViewItems(numItems) {
- if (this.state.skeletonViewItems.length === numItems) {
- return;
- }
-
- if (this.state.skeletonViewItems.length > numItems) {
- this.setState((prevState) => ({
- skeletonViewItems: prevState.skeletonViewItems.slice(0, numItems),
- }));
- return;
- }
-
- const skeletonViewItems = [];
- for (let i = this.state.skeletonViewItems.length; i < numItems; i++) {
- const step = i % 3;
- let lineWidth;
- switch (step) {
- case 0:
- lineWidth = '100%';
- break;
- case 1:
- lineWidth = '50%';
- break;
- default:
- lineWidth = '25%';
- }
- skeletonViewItems.push(
-
-
-
-
- ,
- );
- }
-
- this.setState((prevState) => ({
- skeletonViewItems: [...prevState.skeletonViewItems, ...skeletonViewItems],
- }));
- }
-
- render() {
- return (
- {
- const numItems = Math.ceil(event.nativeEvent.layout.height / CONST.LHN_SKELETON_VIEW_ITEM_HEIGHT);
- this.generateSkeletonViewItems(numItems);
- }}
- >
- {this.state.skeletonViewItems}
-
- );
- }
-}
-
-OptionsListSkeletonView.propTypes = propTypes;
-OptionsListSkeletonView.defaultProps = defaultTypes;
-
-export default compose(withThemeStyles, withTheme)(OptionsListSkeletonView);
diff --git a/src/components/OptionsListSkeletonView.tsx b/src/components/OptionsListSkeletonView.tsx
new file mode 100644
index 000000000000..9f60f1e5fc40
--- /dev/null
+++ b/src/components/OptionsListSkeletonView.tsx
@@ -0,0 +1,83 @@
+import React, {useMemo, useState} from 'react';
+import {View} from 'react-native';
+import {Circle, Rect} from 'react-native-svg';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
+import CONST from '@src/CONST';
+import SkeletonViewContentLoader from './SkeletonViewContentLoader';
+
+type OptionsListSkeletonViewProps = {
+ shouldAnimate?: boolean;
+};
+
+function OptionsListSkeletonView({shouldAnimate = true}: OptionsListSkeletonViewProps) {
+ const theme = useTheme();
+ const themeStyles = useThemeStyles();
+
+ const [numItems, setNumItems] = useState(0);
+ const skeletonViewItems = useMemo(() => {
+ const items = [];
+ for (let i = 0; i < numItems; i++) {
+ const step = i % 3;
+ let lineWidth;
+ switch (step) {
+ case 0:
+ lineWidth = '100%';
+ break;
+ case 1:
+ lineWidth = '50%';
+ break;
+ default:
+ lineWidth = '25%';
+ }
+ items.push(
+
+
+
+
+ ,
+ );
+ }
+ return items;
+ }, [numItems, shouldAnimate, theme, themeStyles]);
+
+ return (
+ {
+ const newNumItems = Math.ceil(event.nativeEvent.layout.height / CONST.LHN_SKELETON_VIEW_ITEM_HEIGHT);
+ if (newNumItems === numItems) {
+ return;
+ }
+ setNumItems(newNumItems);
+ }}
+ >
+ {skeletonViewItems}
+
+ );
+}
+
+OptionsListSkeletonView.displayName = 'OptionsListSkeletonView';
+
+export default OptionsListSkeletonView;