Skip to content
This repository was archived by the owner on Aug 30, 2025. It is now read-only.

Commit 558ef79

Browse files
committed
refactor(Home): optimiser les composants avec memo et implémenter le chargement paresseux pour améliorer les performances
1 parent e9756e0 commit 558ef79

File tree

5 files changed

+52
-81
lines changed

5 files changed

+52
-81
lines changed

src/components/Home/RedirectButton.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
1-
import type React from "react";
1+
import React, { memo, useCallback } from "react";
22
import { View, Text } from "react-native";
33
import { ArrowUpRight } from "lucide-react-native";
44
import { NavigationContainerRef, useTheme } from "@react-navigation/native";
55
import { TouchableOpacity } from "react-native-gesture-handler";
66
import type { RouteParameters } from "@/router/helpers/types";
77

88
interface RedirectButtonProps {
9-
navigation: NavigationContainerRef<RouteParameters> | null,
10-
redirect: keyof RouteParameters
9+
navigation: NavigationContainerRef<RouteParameters> | null;
10+
redirect: keyof RouteParameters;
1111
}
1212

1313
const RedirectButton: React.FC<RedirectButtonProps> = ({ navigation, redirect }) => {
1414
const theme = useTheme();
1515
const { colors } = theme;
1616

17+
const handlePress = useCallback(() => {
18+
navigation?.navigate(redirect);
19+
}, [navigation, redirect]);
20+
1721
return (
18-
<TouchableOpacity
19-
// @ts-expect-error : on ne prend pas le state des routes en compte ici.
20-
onPress={() => navigation?.navigate(redirect)}
21-
>
22+
<TouchableOpacity onPress={handlePress}>
2223
<View
2324
style={{
2425
flexDirection: "row",
@@ -37,7 +38,6 @@ const RedirectButton: React.FC<RedirectButtonProps> = ({ navigation, redirect })
3738
<Text style={{ color: colors.text, fontSize: 15, fontFamily: "semibold" }}>
3839
Voir plus
3940
</Text>
40-
4141
<ArrowUpRight
4242
strokeWidth={2.5}
4343
size={20}
@@ -48,4 +48,4 @@ const RedirectButton: React.FC<RedirectButtonProps> = ({ navigation, redirect })
4848
);
4949
};
5050

51-
export default RedirectButton;
51+
export default memo(RedirectButton);

src/components/Home/Widget.tsx

Lines changed: 15 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,7 @@
1-
import React, { type FunctionComponent, RefAttributes, useEffect, useRef, useState } from "react";
1+
import React, { useCallback, useEffect, useRef, useState, memo } from "react";
22
import { ActivityIndicator, StyleSheet } from "react-native";
3-
43
import { useTheme } from "@react-navigation/native";
5-
6-
import Reanimated, {
7-
FadeIn,
8-
FadeOut,
9-
LinearTransition,
10-
ZoomIn
11-
} from "react-native-reanimated";
12-
4+
import Reanimated, { FadeIn, FadeOut, LinearTransition, ZoomIn } from "react-native-reanimated";
135
import { animPapillon } from "@/utils/ui/animations";
146
import { PressableScale } from "react-native-pressable-scale";
157
import { NativeText } from "../Global/NativeComponents";
@@ -18,8 +10,8 @@ import type { RouteParameters } from "@/router/helpers/types";
1810
import { useOnlineStatus } from "@/hooks/useOnlineStatus";
1911

2012
interface WidgetContainerProps {
21-
widget: React.ForwardRefExoticComponent<WidgetProps & RefAttributes<unknown>>
22-
navigation?: NativeStackNavigationProp<RouteParameters, keyof RouteParameters>
13+
widget: React.ForwardRefExoticComponent<WidgetProps & React.RefAttributes<unknown>>;
14+
navigation?: NativeStackNavigationProp<RouteParameters, keyof RouteParameters>;
2315
}
2416

2517
export interface WidgetProps {
@@ -32,7 +24,7 @@ export interface WidgetProps {
3224
const Widget: React.FC<WidgetContainerProps> = ({ widget: DynamicWidget, navigation }) => {
3325
const theme = useTheme();
3426
const { colors } = theme;
35-
const widgetRef = useRef<FunctionComponent<WidgetProps> | null>(null);
27+
const widgetRef = useRef<React.FunctionComponent<WidgetProps> | null>(null);
3628
const { isOnline } = useOnlineStatus();
3729

3830
const [loading, setLoading] = useState(true);
@@ -44,12 +36,12 @@ const Widget: React.FC<WidgetContainerProps> = ({ widget: DynamicWidget, navigat
4436
}
4537
}, [isOnline, loading]);
4638

47-
const handlePress = () => {
39+
const handlePress = useCallback(() => {
4840
const location = (widgetRef.current as any)?.handlePress();
4941
if (location) {
5042
navigation?.navigate(location);
5143
}
52-
};
44+
}, [navigation]);
5345

5446
return (
5547
<Reanimated.View
@@ -61,22 +53,11 @@ const Widget: React.FC<WidgetContainerProps> = ({ widget: DynamicWidget, navigat
6153
entering={animPapillon(ZoomIn).withInitialValues({ transform: [{ scale: 0.7 }], opacity: 0 })}
6254
exiting={FadeOut.duration(150)}
6355
>
64-
<PressableScale
65-
onPress={() => handlePress()}
66-
>
56+
<PressableScale onPress={handlePress}>
6757
<Reanimated.View
68-
entering={
69-
FadeIn.springify().mass(1).damping(20).stiffness(300)
70-
}
71-
exiting={
72-
FadeOut
73-
}
74-
style={[
75-
styles.widget,
76-
{
77-
backgroundColor: colors.card,
78-
}
79-
]}
58+
entering={FadeIn.springify().mass(1).damping(20).stiffness(300)}
59+
exiting={FadeOut}
60+
style={[styles.widget, { backgroundColor: colors.card }]}
8061
>
8162
{loading && (
8263
<Reanimated.View
@@ -94,20 +75,17 @@ const Widget: React.FC<WidgetContainerProps> = ({ widget: DynamicWidget, navigat
9475
exiting={FadeOut.duration(150)}
9576
>
9677
<ActivityIndicator />
97-
<NativeText variant="subtitle">
98-
Chargement...
99-
</NativeText>
78+
<NativeText variant="subtitle">Chargement...</NativeText>
10079
</Reanimated.View>
10180
)}
102-
10381
<Reanimated.View
10482
style={[
10583
styles.widgetContent,
10684
{
10785
backgroundColor: theme.dark ? colors.primary + "09" : colors.primary + "11",
10886
overflow: "hidden",
10987
opacity: loading ? 0 : 1,
110-
}
88+
},
11189
]}
11290
>
11391
<DynamicWidget
@@ -118,7 +96,6 @@ const Widget: React.FC<WidgetContainerProps> = ({ widget: DynamicWidget, navigat
11896
hidden={hidden}
11997
/>
12098
</Reanimated.View>
121-
12299
</Reanimated.View>
123100
</PressableScale>
124101
</Reanimated.View>
@@ -135,14 +112,10 @@ const styles = StyleSheet.create({
135112
borderRadius: 17,
136113
borderCurve: "continuous",
137114
shadowColor: "#000",
138-
shadowOffset: {
139-
width: 0,
140-
height: 0.5,
141-
},
115+
shadowOffset: { width: 0, height: 0.5 },
142116
shadowOpacity: 0.3,
143117
shadowRadius: 3,
144118
},
145-
146119
widgetContent: {
147120
width: "100%",
148121
height: "100%",
@@ -152,4 +125,4 @@ const styles = StyleSheet.create({
152125
},
153126
});
154127

155-
export default Widget;
128+
export default memo(Widget);

src/components/Home/WidgetHeader.tsx

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1+
import React, { memo } from "react";
12
import { useTheme } from "@react-navigation/native";
2-
import React, { cloneElement } from "react";
33
import { View, Text, ActivityIndicator } from "react-native";
44

55
const WidgetHeader: React.FC<{
6-
title: string
7-
icon?: React.ReactElement
8-
loading?: boolean
6+
title: string;
7+
icon?: React.ReactElement;
8+
loading?: boolean;
99
}> = ({ icon, title, loading }) => {
1010
const theme = useTheme();
1111
const { colors } = theme;
1212

13-
const clonedIcon = icon && cloneElement(icon, {
13+
const clonedIcon = icon && React.cloneElement(icon, {
1414
size: 20,
1515
strokeWidth: 2.3,
1616
color: colors.text,
@@ -27,7 +27,6 @@ const WidgetHeader: React.FC<{
2727
}}
2828
>
2929
{clonedIcon}
30-
3130
<Text
3231
style={{
3332
color: colors.text,
@@ -38,12 +37,9 @@ const WidgetHeader: React.FC<{
3837
>
3938
{title}
4039
</Text>
41-
42-
{loading && (
43-
<ActivityIndicator />
44-
)}
40+
{loading && <ActivityIndicator />}
4541
</View>
4642
);
4743
};
4844

49-
export default WidgetHeader;
45+
export default memo(WidgetHeader);

src/views/account/Home/ElementIndex.tsx

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,32 @@
1-
import AttendanceElement from "./Elements/AttendanceElement";
2-
import GradesElement from "./Elements/GradesElement";
3-
import HomeworksElement from "./Elements/HomeworksElement";
4-
import TimetableElement from "./Elements/TimetableElement";
5-
import React from "react";
1+
import React, { lazy } from "react";
62

7-
export const Elements = [
3+
// Lazy load components to improve initial load performance
4+
const AttendanceElement = lazy(() => import("./Elements/AttendanceElement"));
5+
const GradesElement = lazy(() => import("./Elements/GradesElement"));
6+
const HomeworksElement = lazy(() => import("./Elements/HomeworksElement"));
7+
const TimetableElement = lazy(() => import("./Elements/TimetableElement"));
8+
9+
export type Element = {
10+
id: string;
11+
component: React.LazyExoticComponent<React.FC<any>>; // Use LazyExoticComponent for lazy-loaded components
12+
importance?: number;
13+
};
14+
15+
export const Elements: Element[] = [
816
{
9-
id: "timetable",
17+
id: "timetable",
1018
component: TimetableElement,
1119
},
1220
{
13-
id: "grades",
21+
id: "grades",
1422
component: GradesElement,
1523
},
1624
{
17-
id: "attendance",
25+
id: "attendance",
1826
component: AttendanceElement,
1927
},
2028
{
21-
id: "homeworks",
29+
id: "homeworks",
2230
component: HomeworksElement,
23-
}
31+
},
2432
];
25-
26-
export type Element = {
27-
id: string
28-
component: React.FC<any>
29-
importance?: number
30-
};

src/views/account/Home/ModalContent.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useCallback, useEffect, useState, useMemo } from "react";
1+
import React, { useCallback, useEffect, useState, useMemo, memo } from "react";
22
import { NativeList, NativeText } from "@/components/Global/NativeComponents";
33
import Reanimated, { FadeInUp, FadeOutDown, LinearTransition } from "react-native-reanimated";
44
import { Sparkles, X } from "lucide-react-native";
@@ -169,4 +169,4 @@ const ModalContent: React.FC<ModalContentProps> = ({ navigation, refresh, endRef
169169
);
170170
};
171171

172-
export default ModalContent;
172+
export default memo(ModalContent);

0 commit comments

Comments
 (0)