Skip to content

feedback changes - #78

Merged
Manan-Sharma-5 merged 1 commit into
devfrom
feedback-27-jan
Jan 27, 2025
Merged

Manan-Sharma-5 merged 1 commit into
devfrom
feedback-27-jan

Conversation

@Manan-Sharma-5

@Manan-Sharma-5 Manan-Sharma-5 commented Jan 27, 2025 •

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

Based on the comprehensive pull request summary, here are the concise release notes:

  • New Features

    • Enhanced social media handle display for influencer profiles
    • Improved text truncation for descriptions across multiple components
  • UI/UX Improvements

    • Refined layout and spacing in collaboration and contract card components
    • Added responsive design adjustments for proposal and invitation lists
    • Platform-specific navigation button handling
  • Performance

    • Optimized text rendering with dynamic truncation
    • Improved component layout flexibility
  • Bug Fixes

    • Streamlined component rendering and styling consistency

@coderabbitai

coderabbitai Bot commented Jan 27, 2025 •

Copy link
Copy Markdown

Walkthrough

This pull request introduces a series of UI and functionality improvements across multiple components. The changes focus on enhancing user interface consistency, implementing platform-specific navigation, and improving text rendering. Key modifications include adding a truncateText utility, updating navigation button handling in the pre-signin screen, fetching influencer handles from Firestore, and making layout adjustments to various components like collaboration cards, contract details, and proposal lists.

Changes

File Change Summary
app/(auth)/pre-signin.tsx Added platform-specific navigation button handling for Swiper component
components/InfluencerCard.tsx Implemented Firestore-based handle fetching for influencer social media
components/collaboration-card/* Added text truncation and adjusted layout spacing
components/collaboration/collaboration-details/OverviewTabContent.tsx Modified text truncation length and layout spacing
components/contract-* Updated layout styles and text rendering
components/proposals/* Adjusted FlatList layout for responsive design
styles/* Removed width constraints and added flex properties

Sequence Diagram

sequenceDiagram
    participant User
    participant PreSigninScreen
    participant Swiper
    participant Firestore

    User->>PreSigninScreen: Navigates to screen
    PreSigninScreen->>Swiper: Render with platform-specific buttons
    Swiper-->>PreSigninScreen: Display navigation
    
    User->>InfluencerCard: Views card
    InfluencerCard->>Firestore: Fetch handle
    Firestore-->>InfluencerCard: Return handle
    InfluencerCard->>User: Display influencer details
Loading

Possibly related PRs

Suggested reviewers

  • dev-rathore

Poem

🐰 A Rabbit's Ode to UI Delight

Buttons dance on web and mobile's stage,
Truncated text turns a new page,
Firestore whispers handles so bright,
Flex and style take playful flight,
Code hops with joy, a pixel's might! 🎨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (11)
components/proposals/Invitations.tsx (2)

218-219: LGTM! Responsive layout improvements look good.

The changes improve the layout responsiveness by:

  • Implementing a 2-column grid layout for larger screens
  • Ensuring proper spacing between columns
  • Adding adequate bottom padding for better scrolling experience

However, consider adding a comment explaining the increased paddingBottom value for better maintainability.

  contentContainerStyle={{
    gap: 16,
-   paddingBottom: 64,
+   // Additional padding to account for the bottom navigation bar
+   paddingBottom: 64,
    width: xl ? "50%" : "100%",
  }}

Also applies to: 229-229, 232-234


Line range hint 42-93: Consider improving error handling and loading states.

The fetchProposals function could benefit from:

  1. More granular loading states for better UX
  2. User-friendly error handling
  3. Query optimization to reduce Firestore reads
 const fetchProposals = async () => {
+  const loadingStates = {
+    proposals: false,
+    applications: false,
+    invitations: false,
+  };
   try {
+    setError(null);
+    loadingStates.proposals = true;
     const collaborationCol = collection(FirestoreDB, "collaborations");
     const q = query(
       collaborationCol,
       where("brandId", "==", selectedBrand?.id)
     );
     const querySnapshot = await getDocs(q);
+    loadingStates.proposals = false;
+    loadingStates.applications = true;
+    loadingStates.invitations = true;

     const proposals = await Promise.all(
       querySnapshot.docs.map(async (doc) => {
         const data = {
           ...doc.data(),
           id: doc.id,
         };

         // Batch get applications and invitations
+        const batch = [];
+        batch.push(getDocs(collection(FirestoreDB, "collaborations", data.id, "applications")));
+        batch.push(getDocs(collection(FirestoreDB, "collaborations", data.id, "invitations")));
+        const [applicationSnapshot, invitationSnapshot] = await Promise.all(batch);

         const applications = applicationSnapshot.docs.map((appDoc) =>
           appDoc.data()
         );
         const acceptedApplications = applications.filter(
           (application) => application.status === "accepted"
         ).length;

         const invitations = invitationSnapshot.docs.map((invDoc) =>
           invDoc.data()
         );

         return {
           ...data,
           applications: applications.length,
           invitations: invitations.length,
           acceptedApplications,
         };
       })
     );

     setProposals(proposals);
   } catch (error) {
     console.error("Error fetching proposals: ", error);
+    setError("Failed to fetch proposals. Please try again later.");
   } finally {
     setIsLoading(false);
+    loadingStates.applications = false;
+    loadingStates.invitations = false;
   }
 };
components/proposals/Applications.tsx (2)

242-242: LGTM! Consistent responsive layout implementation.

The changes maintain consistency with the Invitations component, implementing the same responsive layout improvements.

Consider extracting these common FlatList styles into a shared configuration for better maintainability.

+// shared/styles/list-layouts.ts
+export const getResponsiveListStyles = (xl: boolean) => ({
+  contentContainerStyle: {
+    gap: 16,
+    paddingBottom: 64,
+    width: xl ? "50%" : "100%",
+  },
+  numColumns: xl ? 2 : 1,
+  ...(xl && {
+    columnWrapperStyle: {
+      justifyContent: "space-between",
+      gap: 16,
+    },
+  }),
+});

+// In both components:
+const responsiveListStyles = getResponsiveListStyles(xl);
+<FlatList
+  {...responsiveListStyles}
+  // other props
+/>

Also applies to: 251-251, 254-256


Line range hint 276-309: Consider improving the create button's positioning.

The absolute positioning of the create button might overlap with the list content. Consider using a sticky footer or padding to ensure visibility.

-<View
-  style={{
-    position: "absolute",
-    bottom: 0,
-    right: 0,
-    left: 0,
-    paddingTop: 16,
-    paddingHorizontal: 16,
-  }}
->
+<View
+  style={{
+    position: "sticky",
+    bottom: 16,
+    paddingHorizontal: 16,
+    backgroundColor: Colors(theme).background,
+    shadowColor: "#000",
+    shadowOffset: {
+      width: 0,
+      height: -2,
+    },
+    shadowOpacity: 0.25,
+    shadowRadius: 3.84,
+    elevation: 5,
+  }}
+>
components/collaboration-card/card-components/CollaborationDetails.tsx (2)

Line range hint 124-139: Consider using a mapping object for platform icons.

The current implementation uses nested ternaries and repeats faInstagram as a fallback. Consider using a mapping object for better maintainability.

+const PLATFORM_ICONS = {
+  Instagram: faInstagram,
+  Facebook: faFacebook,
+  Youtube: faYoutube,
+} as const;
+
 {platform &&
   platform.map((content, index) => (
     <ChipCard
       key={index}
       chipText={content}
-      chipIcon={
-        content === "Instagram"
-          ? faInstagram
-          : content === "Facebook"
-          ? faFacebook
-          : content === "Youtube"
-          ? faYoutube
-          : faInstagram
-      }
+      chipIcon={PLATFORM_ICONS[content as keyof typeof PLATFORM_ICONS] ?? faInstagram}
     />
   ))}

Line range hint 140-159: Simplify content type icon mapping.

Similar to the platform icons, consider using a mapping object for content type icons.

+const CONTENT_TYPE_ICONS = {
+  Posts: faPanorama,
+  Reels: faFilm,
+  Stories: faHeart,
+  Live: faRecordVinyl,
+  'Product Reviews': faStarHalfStroke,
+} as const;
+
 {contentType &&
   contentType.map((content, index) => (
     <ChipCard
       key={index}
       chipText={content}
-      chipIcon={
-        content === "Posts"
-          ? faPanorama
-          : content === "Reels"
-          ? faFilm
-          : content === "Stories"
-          ? faHeart
-          : content === "Live"
-          ? faRecordVinyl
-          : content === "Product Reviews"
-          ? faStarHalfStroke
-          : faPanorama
-      }
+      chipIcon={CONTENT_TYPE_ICONS[content as keyof typeof CONTENT_TYPE_ICONS] ?? faPanorama}
     />
   ))}
components/collaboration/collaboration-details/OverviewTabContent.tsx (2)

418-419: Document or remove empty callback functions.

If these callbacks are placeholders for future implementation, consider adding TODO comments. If they're not needed, consider removing them from the component props.

-onMapRegionChange={(region) => {}}
-onFormattedAddressChange={(address) => {}}
+// TODO: Implement map region change handler
+onMapRegionChange={(region) => {/* Implementation pending */}}
+// TODO: Implement address change handler
+onFormattedAddressChange={(address) => {/* Implementation pending */}}

319-331: Simplify budget text rendering logic.

The nested ternary with template literals can be simplified for better readability.

-<Text
-  style={{
-    fontSize: 16,
-    color: Colors(theme).text,
-  }}
->
-  Budget:
-  {props.collaboration?.budget?.min ===
-  props.collaboration?.budget?.max
-    ? `$${props.collaboration?.budget?.min}`
-    : `$${props.collaboration?.budget?.min} - $${props.collaboration?.budget?.max}`}
-</Text>
+<Text style={{ fontSize: 16, color: Colors(theme).text }}>
+  {`Budget: $${props.collaboration?.budget?.min}${
+    props.collaboration?.budget?.min !== props.collaboration?.budget?.max
+      ? ` - $${props.collaboration?.budget?.max}`
+      : ''
+  }`}
+</Text>
components/contract-card/ContractHeader.tsx (1)

46-46: Consider removing fixed width constraint on username Text.

While adding flex: 1 improves layout flexibility, the username Text component still has a fixed width: 200 which could cause truncation issues on different screen sizes. Consider using flexbox properties instead.

  <Text
    style={{
      fontSize: 16,
      fontWeight: "bold",
-     width: 200,
+     flexShrink: 1,
    }}
  >
app/(auth)/pre-signin.tsx (1)

Line range hint 100-127: Move inline styles to styles file and consolidate platform checks.

The current implementation has two issues:

  1. Inline styles reduce maintainability and should be moved to the styles file
  2. Platform.OS check is duplicated (lines 53 and 100)

Consider applying these improvements:

- {slide.key !== "connect" && Platform.OS !== "web" && (
-   <Pressable
-     style={{
-       flexDirection: "row",
-       alignItems: "center",
-       justifyContent: "center",
-       marginTop: 15,
-       backgroundColor: Colors(theme).primary,
-       paddingHorizontal: 20,
-       paddingVertical: 10,
-       borderRadius: 5,
-       gap: 10,
-     }}
-     onPress={() => {
-       swiperRef.current?.scrollBy(1);
-     }}
-   >
-     <Text
-       style={{
-         color: Colors(theme).white,
-         fontSize: 16,
-       }}
-     >
-       Next
-     </Text>
-     <FontAwesomeIcon
-       icon={faArrowRight}
-       size={16}
-       color={Colors(theme).white}
-     />
-   </Pressable>
- )}
+ {slide.key !== "connect" && Platform.OS !== "web" && (
+   <Pressable
+     style={styles.nextButton}
+     onPress={() => {
+       swiperRef.current?.scrollBy(1);
+     }}
+   >
+     <Text style={styles.nextButtonText}>Next</Text>
+     <FontAwesomeIcon
+       icon={faArrowRight}
+       size={16}
+       color={Colors(theme).white}
+     />
+   </Pressable>
+ )}

Add these styles to your styles file:

nextButton: {
  flexDirection: "row",
  alignItems: "center",
  justifyContent: "center",
  marginTop: 15,
  backgroundColor: Colors(theme).primary,
  paddingHorizontal: 20,
  paddingVertical: 10,
  borderRadius: 5,
  gap: 10,
},
nextButtonText: {
  color: Colors(theme).white,
  fontSize: 16,
},
components/InfluencerCard.tsx (1)

126-126: Add loading state to handle display.

Consider showing a loading indicator while the handle is being fetched.

- <Text style={styles.handle}>@{handle}</Text>
+ {isLoading ? (
+   <ActivityIndicator size="small" color={Colors(theme).primary} />
+ ) : (
+   <Text style={styles.handle}>@{handle}</Text>
+ )}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ece2935 and dba292c.

📒 Files selected for processing (11)
  • app/(auth)/pre-signin.tsx (5 hunks)
  • components/InfluencerCard.tsx (4 hunks)
  • components/collaboration-card/card-components/CollaborationDetails.tsx (6 hunks)
  • components/collaboration-card/card-components/CollaborationHeader.tsx (2 hunks)
  • components/collaboration/collaboration-details/OverviewTabContent.tsx (9 hunks)
  • components/contract-card/ContractHeader.tsx (3 hunks)
  • components/contracts/ContractDetailContent.tsx (2 hunks)
  • components/proposals/Applications.tsx (2 hunks)
  • components/proposals/Invitations.tsx (2 hunks)
  • styles/CollaborationDetails.styles.tsx (0 hunks)
  • styles/collaboration-details/CollaborationHeader.styles.tsx (1 hunks)
💤 Files with no reviewable changes (1)
  • styles/CollaborationDetails.styles.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
components/collaboration-card/card-components/CollaborationDetails.tsx

[error] 124-139: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (15)
components/collaboration-card/card-components/CollaborationHeader.tsx (2)

66-67: LGTM! Layout improvements enhance consistency.

The increased gap and flex property changes improve spacing and layout consistency across components.


97-97: LGTM! Clean timePosted rendering.

The simplified conditional rendering of timePosted improves code readability while maintaining functionality.

styles/collaboration-details/CollaborationHeader.styles.tsx (2)

5-6: LGTM! Well-structured style definition.

The file follows React Native best practices with proper typing and theme support.


23-26: Great improvement to the layout flexibility!

Adding flex: 1 to the title section is a good change as it allows the content to grow and fill available space while maintaining proper layout structure. This change aligns well with similar modifications in related components.

components/collaboration-card/card-components/CollaborationDetails.tsx (1)

25-25: LGTM! Text truncation improves UI consistency.

The addition of truncateText utility ensures consistent text display across components.

Also applies to: 102-102

components/contracts/ContractDetailContent.tsx (1)

178-178: LGTM! Null-safe text truncation.

The implementation correctly handles potential null/undefined values using the null coalescing operator.

components/collaboration/collaboration-details/OverviewTabContent.tsx (2)

366-369: Use consistent platform icon mapping.

Similar to the suggestion in CollaborationDetails.tsx, consider using a mapping object for platform icons.


382-389: Use consistent content format icon mapping.

Similar to the suggestion in CollaborationDetails.tsx, consider using a mapping object for content format icons.

components/contract-card/ContractHeader.tsx (2)

67-67: LGTM! Good layout improvement.

Adding flex: 1 here creates a proper flex layout hierarchy, allowing the text container to grow appropriately within its parent.


97-97: Consider adding timestamp validation.

While the code simplification is good, consider adding validation for the timestamp to handle potential invalid values.

- {timePosted ? <Text>{formatTimeToNow(timePosted)}</Text> : null}
+ {timePosted && !isNaN(timePosted) ? <Text>{formatTimeToNow(timePosted)}</Text> : null}

Let's verify the formatTimeToNow implementation:

app/(auth)/pre-signin.tsx (3)

2-2: LGTM! Import changes align with new features.

The added imports support the platform-specific navigation implementation.

Also applies to: 16-17


86-87: LGTM! Theme-consistent button styling.

The button color changes improve visual consistency by properly utilizing theme colors.


53-75: Verify the buttonWrapper styles are defined.

The navigation buttons reference styles.buttonWrapper, but this style isn't visible in the provided code. Ensure it's properly defined in the styles file.

✅ Verification successful

The buttonWrapper style is properly defined

The style is correctly defined in styles/tab1.styles.tsx with appropriate styling for the navigation buttons, including background color, border radius, and padding properties.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for buttonWrapper style definition
rg -A 5 "buttonWrapper.*[:=]" --type tsx

Length of output: 70


Script:

#!/bin/bash
# Search for buttonWrapper styles with multiple file extensions
rg -A 5 "buttonWrapper.*[:=]" --type ts --type js --type jsx --type tsx

# Check the specific file content
cat "app/(auth)/pre-signin.tsx"

Length of output: 5256


Script:

#!/bin/bash
# Find and check the contents of the styles file
fd "tab1.styles" --type f
cat "styles/tab1.styles.ts" || cat "styles/tab1.styles.js"

Length of output: 212


Script:

#!/bin/bash
# Check the contents of the correct styles file
cat "styles/tab1.styles.tsx"

Length of output: 1437

components/InfluencerCard.tsx (2)

35-37: LGTM! Clean import additions.

The new Firestore imports are properly organized and necessary for the added functionality.


Line range hint 1-248: Verify component usage across the application.

Let's ensure that these changes don't affect other parts of the application that might be using this component.

✅ Verification successful

Changes are safe and improve data access patterns ✅

The component is only used in components/explore-influencers/index.tsx and the changes make the social handle fetching more robust by properly accessing Firestore data instead of direct array access. No other components are affected by these changes.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for InfluencerCard usage
echo "Searching for InfluencerCard imports and usage..."
rg "import.*InfluencerCard|<InfluencerCard" --type tsx --type ts

# Search for any direct access to influencer.socials that might be affected
echo "Checking for direct access to influencer.socials..."
rg "influencer\.socials\[" --type tsx --type ts

Length of output: 394


Script:

#!/bin/bash
# Find all TypeScript and TypeScript React files first
echo "Finding TypeScript files..."
fd "\.(tsx|ts)$"

echo -e "\nSearching for InfluencerCard usage..."
fd "\.(tsx|ts)$" | xargs rg "import.*InfluencerCard|<InfluencerCard"

echo -e "\nChecking for direct access to influencer.socials..."
fd "\.(tsx|ts)$" | xargs rg "influencer\.socials\["

Length of output: 10266

Comment on lines 89 to 96
useEffect(() => {
if (props?.alreadyInvited) {
props.alreadyInvited(props.influencer.id).then((invited) => {
setIsInvited(invited);
});
}
fetchHandle();
}, []);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Update useEffect dependencies and handle concurrent operations.

The current useEffect implementation has potential issues:

  1. Missing dependency on influencer.primarySocial
  2. Concurrent API calls could lead to race conditions

Consider separating the effects:

- useEffect(() => {
-   if (props?.alreadyInvited) {
-     props.alreadyInvited(props.influencer.id).then((invited) => {
-       setIsInvited(invited);
-     });
-   }
-   fetchHandle();
- }, []);

+ useEffect(() => {
+   if (props?.alreadyInvited) {
+     props.alreadyInvited(props.influencer.id).then((invited) => {
+       setIsInvited(invited);
+     });
+   }
+ }, [props?.alreadyInvited, props.influencer.id]);
+
+ useEffect(() => {
+   const cleanup = fetchHandle();
+   return cleanup;
+ }, [influencer.primarySocial]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
if (props?.alreadyInvited) {
props.alreadyInvited(props.influencer.id).then((invited) => {
setIsInvited(invited);
});
}
fetchHandle();
}, []);
useEffect(() => {
if (props?.alreadyInvited) {
props.alreadyInvited(props.influencer.id).then((invited) => {
setIsInvited(invited);
});
}
}, [props?.alreadyInvited, props.influencer.id]);
useEffect(() => {
fetchHandle();
}, [props.influencer?.primarySocial]);

Comment on lines +66 to +87
const fetchHandle = async () => {
if (!influencer.primarySocial) {
setHandle("influencer-handle");
return;
}
const userSocialRef = doc(
FirestoreDB,
"users",
influencer.id,
"socials",
influencer.primarySocial
);
const socialDoc = await getDoc(userSocialRef);
const socialData = socialDoc.data() as ISocials;
if (socialDoc.exists()) {
if (socialData.isInstagram) {
setHandle(socialData.instaProfile?.username || "influencer-handle");
} else {
setHandle(socialData.fbProfile?.name || "influencer-handle");
}
}
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling and loading state to the Firestore fetch.

The fetchHandle function needs improvements in error handling and user experience:

  1. Add error handling for Firestore operations
  2. Prevent state updates if component unmounts
  3. Add loading state while fetching
  4. Consider moving the fallback value to constants

Here's a suggested implementation:

+ const [isLoading, setIsLoading] = useState(false);
+ const DEFAULT_HANDLE = "influencer-handle";

  const fetchHandle = async () => {
+   setIsLoading(true);
    if (!influencer.primarySocial) {
-     setHandle("influencer-handle");
+     setHandle(DEFAULT_HANDLE);
+     setIsLoading(false);
      return;
    }
+   
+   let isMounted = true;
    try {
      const userSocialRef = doc(
        FirestoreDB,
        "users",
        influencer.id,
        "socials",
        influencer.primarySocial
      );
      const socialDoc = await getDoc(userSocialRef);
      const socialData = socialDoc.data() as ISocials;
-     if (socialDoc.exists()) {
+     if (socialDoc.exists() && isMounted) {
        if (socialData.isInstagram) {
-         setHandle(socialData.instaProfile?.username || "influencer-handle");
+         setHandle(socialData.instaProfile?.username || DEFAULT_HANDLE);
        } else {
-         setHandle(socialData.fbProfile?.name || "influencer-handle");
+         setHandle(socialData.fbProfile?.name || DEFAULT_HANDLE);
        }
      }
+   } catch (error) {
+     console.error('Error fetching handle:', error);
+     if (isMounted) {
+       setHandle(DEFAULT_HANDLE);
+     }
+   } finally {
+     if (isMounted) {
+       setIsLoading(false);
+     }
    }
+   
+   return () => {
+     isMounted = false;
+   };
  };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const fetchHandle = async () => {
if (!influencer.primarySocial) {
setHandle("influencer-handle");
return;
}
const userSocialRef = doc(
FirestoreDB,
"users",
influencer.id,
"socials",
influencer.primarySocial
);
const socialDoc = await getDoc(userSocialRef);
const socialData = socialDoc.data() as ISocials;
if (socialDoc.exists()) {
if (socialData.isInstagram) {
setHandle(socialData.instaProfile?.username || "influencer-handle");
} else {
setHandle(socialData.fbProfile?.name || "influencer-handle");
}
}
};
const [isLoading, setIsLoading] = useState(false);
const DEFAULT_HANDLE = "influencer-handle";
const isMounted = useRef(true);
useEffect(() => {
return () => {
isMounted.current = false;
};
}, []);
const fetchHandle = async () => {
setIsLoading(true);
if (!influencer.primarySocial) {
setHandle(DEFAULT_HANDLE);
setIsLoading(false);
return;
}
try {
const userSocialRef = doc(
FirestoreDB,
"users",
influencer.id,
"socials",
influencer.primarySocial
);
const socialDoc = await getDoc(userSocialRef);
const socialData = socialDoc.data() as ISocials;
if (socialDoc.exists() && isMounted.current) {
if (socialData.isInstagram) {
setHandle(socialData.instaProfile?.username || DEFAULT_HANDLE);
} else {
setHandle(socialData.fbProfile?.name || DEFAULT_HANDLE);
}
}
} catch (error) {
console.error('Error fetching handle:', error);
if (isMounted.current) {
setHandle(DEFAULT_HANDLE);
}
} finally {
if (isMounted.current) {
setIsLoading(false);
}
}
};

@Manan-Sharma-5
Manan-Sharma-5 merged commit 9223b4d into dev Jan 27, 2025
This was referenced Jan 27, 2025
Merged
@coderabbitai coderabbitai Bot mentioned this pull request Mar 22, 2025
@coderabbitai coderabbitai Bot mentioned this pull request Jun 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants