<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Dheeraj Bartwal on Medium]]></title>
        <description><![CDATA[Stories by Dheeraj Bartwal on Medium]]></description>
        <link>https://medium.com/@dheeraj.bartwal91?source=rss-4972a447592------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*PogagChX0rGuKd9xUFUuwA.png</url>
            <title>Stories by Dheeraj Bartwal on Medium</title>
            <link>https://medium.com/@dheeraj.bartwal91?source=rss-4972a447592------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Tue, 19 May 2026 08:33:48 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@dheeraj.bartwal91/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[ Building a Real-Time Chat App in React Native with CometChat]]></title>
            <link>https://medium.com/@dheeraj.bartwal91/building-a-real-time-chat-app-in-react-native-with-cometchat-8d23afbdf05f?source=rss-4972a447592------2</link>
            <guid isPermaLink="false">https://medium.com/p/8d23afbdf05f</guid>
            <category><![CDATA[real-time-messaging]]></category>
            <category><![CDATA[react-native]]></category>
            <category><![CDATA[chat-apps]]></category>
            <category><![CDATA[cometchat]]></category>
            <dc:creator><![CDATA[Dheeraj Bartwal]]></dc:creator>
            <pubDate>Sat, 14 Jun 2025 09:51:58 GMT</pubDate>
            <atom:updated>2025-06-14T09:56:12.630Z</atom:updated>
            <content:encoded><![CDATA[<blockquote>In today’s mobile-first world, real-time communication is an expectation, not a luxury. In this post, I’ll walk you through the architecture and implementation of a production-ready chat interface built with React Native and CometChat — inspired by real-world telehealth and advisory platforms where users engage in time-bound, scheduled conversations.</blockquote><h3>👨‍💻 What We Built</h3><p>We created a <strong>chat screen</strong> and a <strong>conversation list</strong> using @cometchat/chat-sdk-react-native, tailored for <strong>session-based communication</strong>—meaning chats are only active during a scheduled window (e.g., therapy, tutoring, consultations).</p><h3>🔑 Key Features</h3><ul><li>✅ Chat starts and ends based on appointment schedule</li><li>📷 Real-time messaging with image support</li><li>✍️ Typing indicators, user online/offline status</li><li>⏱ Countdown timer for active session</li><li>🛑 Automatic chat termination after time limit</li><li>🧼 Media validation (no GIFs, file size checks)</li><li>📜 Optimized message history loading</li></ul><h3>📱 Conversations Screen — Recent Contacts &amp; History</h3><p>The Conversations.tsx screen fetches the user’s recent chats and displays:</p><ul><li>A horizontal list of <strong>Recent Contacts</strong></li><li>A vertical list of <strong>Active Conversations</strong></li></ul><h3>📦 Fetching Conversations</h3><pre>const fetchConversations = async (allConversations: boolean) =&gt; {<br>  const conversationsList =<br>    await CometChatService.getInstance().fetchNextConversations(allConversations);<br>setConversations(prevConversations =&gt; {<br>    const processedConversations = conversationsList.map(conv =&gt; ({<br>      conversationWith: conv.conversationWith,<br>      lastMessage: {<br>        text: conv.lastMessage?.text || &#39;Image&#39;,<br>        sentAt: conv.lastMessage?.sentAt || Date.now(),<br>      },<br>      unreadMessageCount: conv.unreadMessageCount || 0,<br>      conversationId: conv.conversationId,<br>    }));<br>    return [...processedConversations].sort(<br>      (a, b) =&gt; (b.lastMessage?.sentAt || 0) - (a.lastMessage?.sentAt || 0)<br>    );<br>  });<br>};</pre><h3>🧭 Navigating to a Chat</h3><pre>&lt;TouchableOpacity<br>  onPress={() =&gt;<br>    navigation.navigate(SCREEN_NAME.CHAT_SCREEN, {<br>      senderDetails: item.conversationWith,<br>    })<br>  }&gt;</pre><h3>💬 Chat Screen — Real-Time Messaging with Media</h3><p>The ChatScreen.tsx handles:</p><ul><li>Realtime message rendering</li><li>User presence</li><li>Scheduled session restrictions</li><li>Media file uploads</li></ul><h3>📤 Message Sending Logic</h3><pre>const handleSend = async () =&gt; {<br>  const sentMessage = await CometChatService.getInstance().sendMessage(<br>    senderDetails.uid,<br>    message.trim(),<br>  );<br><br>const newMessage: ChatMessage = {<br>    _id: sentMessage.id,<br>    createdAt: new Date(sentMessage.sentAt * 1000),<br>    user: {<br>      _id: sentMessage.sender.uid,<br>      name: sentMessage.sender.name,<br>    },<br>    messageText: sentMessage.text,<br>    image: sentMessage.sender.avatar,<br>  };<br>  setMessages(prev =&gt; [newMessage, ...prev]);<br>  setMessage(&#39;&#39;);<br>};</pre><h3>🖼 Media Message Handling (Camera &amp; Gallery)</h3><p>Media validation and image message sending:</p><pre>const handleSendMediaMessage = async (mediaFile: MediaData) =&gt; {<br>  const sentMessage = await CometChatService.getInstance().sendMediaMessage(<br>    senderDetails.uid,<br>    mediaFile,<br>  );<br><br>const newMessage: ChatMessage = {<br>    _id: sentMessage.id,<br>    createdAt: new Date(sentMessage.sentAt * 1000),<br>    user: {<br>      _id: sentMessage.sender.uid,<br>      name: sentMessage.sender.name,<br>    },<br>    messageText: &#39;User_has_sent_an_image&#39;,<br>    image: sentMessage.sender.avatar,<br>    mediaUrl: sentMessage.data?.url,<br>  };<br>  setMessages(prev =&gt; [newMessage, ...prev]);<br>};</pre><p>Rejecting GIFs and large files:</p><pre>if (type === &#39;image/gif&#39;) {<br>  errorToast(&#39;GIFs are not allowed&#39;);<br>  return;<br>}<br>if (validateFileSize(fileSize)) {<br>  errorToast(FILE_EXCEED_ERROR_MESSAGE);<br>  return;<br>}</pre><h3>🕓 Session Timer &amp; Auto Chat-End</h3><p>If the user has a scheduled booking, chat only opens during that window.</p><h3>⏳ Start Timer</h3><pre>const startTimer = () =&gt; {<br>  BackgroundTimer.runBackgroundTimer(() =&gt; {<br>    setRemainingTime(prev =&gt; {<br>      if (prev &lt;= 1) {<br>        BackgroundTimer.stopBackgroundTimer();<br>        handleAutoChatEnd();<br>        return 0;<br>      }<br>if (prev === 300 &amp;&amp; !alertShown) {<br>        errorToast(&#39;The chat will end in 5 minutes.&#39;);<br>        setAlertShown(true);<br>      }<br>      return prev - 1;<br>    });<br>  }, 1000);<br>};</pre><h3>🔚 Auto-End Logic</h3><pre>const handleAutoChatEnd = () =&gt; {<br>  if (chatEndTriggeredRef.current) return;<br><br>chatEndTriggeredRef.current = true;<br>  dispatch(<br>    endChat({<br>      data: apiPayload,<br>      cb: () =&gt; {<br>        setIsConfirmText(false);<br>        setIsConfirmChatEnd(true);<br>      },<br>    }),<br>  );<br>};</pre><h3>🔄 Typing &amp; User Presence</h3><p>Handle real-time presence and typing indicators using CometChat events.</p><pre>CometChatService.getInstance().attachMessageListener(<br>  listenerId,<br>  (event, message) =&gt; {<br>    if (event === MessageEvents.TYPING_STARTED) setIsTyping(true);<br>    else if (event === MessageEvents.TYPING_ENDED) setIsTyping(false);<br>    else if (event === MessageEvents.USER_ONLINE) setIsUserOnline(true);<br>    else if (event === MessageEvents.USER_OFFLINE) setIsUserOnline(false);<br>  }<br>);</pre><p>Typing trigger based on keyboard visibility:</p><pre>useEffect(() =&gt; {<br>  if (isKeyboardVisible) {<br>    CometChat.startTyping(new CometChat.TypingIndicator(senderDetails.uid, &#39;user&#39;));<br>  } else {<br>    CometChat.endTyping(new CometChat.TypingIndicator(senderDetails.uid, &#39;user&#39;));<br>  }<br>}, [isKeyboardVisible]);</pre><h3>🧠 Final Thoughts</h3><p>Building a real-time, session-aware chat interface involves much more than just messaging SDK integration.</p><p>By layering:</p><ul><li>⏱ session timers</li><li>🛂 role-based access control</li><li>🚨 UI feedback (toasts)</li><li>🔒 file validation</li><li>🔁 real-time hooks</li></ul><p>…we ensure a <strong>robust</strong> user experience that respects both UX and business rules.</p><h3>🛠 Tech Stack</h3><ul><li><strong>React Native</strong></li><li><strong>CometChat SDK</strong></li><li><strong>Redux, React Navigation</strong></li><li><strong>react-native-background-timer</strong></li><li><strong>Moment.js</strong>, <strong>FlatList</strong></li></ul><h3>👨‍💼 Work With Me</h3><p>If you’re building a <strong>React Native</strong> or <strong>iOS native</strong> app and need an experienced engineer to <strong>ship fast, scalable, and reliable solutions</strong>, I’m available for freelance and contract work.</p><p>📫 Let’s connect on <a href="https://linkedin.com">LinkedIn</a> or reach out via email to discuss your project!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8d23afbdf05f" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[ Mastering Forms in React Native with React Hook Form: Optimized Performance & Minimal Re-Renders]]></title>
            <link>https://medium.com/@dheeraj.bartwal91/mastering-forms-in-react-native-with-react-hook-form-optimized-performance-minimal-re-renders-623ab9e19f3b?source=rss-4972a447592------2</link>
            <guid isPermaLink="false">https://medium.com/p/623ab9e19f3b</guid>
            <category><![CDATA[react-form-handling]]></category>
            <category><![CDATA[react-native]]></category>
            <category><![CDATA[react-form-validation]]></category>
            <category><![CDATA[react-forms]]></category>
            <dc:creator><![CDATA[Dheeraj Bartwal]]></dc:creator>
            <pubDate>Fri, 07 Feb 2025 10:58:41 GMT</pubDate>
            <atom:updated>2025-02-07T10:58:41.029Z</atom:updated>
            <content:encoded><![CDATA[<p>Forms are an essential part of any mobile app, whether for user authentication, feedback, or data collection. In React Native, handling forms efficiently can be tricky, especially when performance is a concern. <strong>React Hook Form </strong>is a powerful library that simplifies form handling while improving performance by minimizing re-renders.</p><p>In this article, we’ll explore how <strong>React Hook Form prevents unnecessary re-renders</strong> and improves the user experience in React Native applications.</p><h3>🔥 Why Use React Hook Form in React Native?</h3><p>React Hook Form offers multiple benefits over traditional form-handling methods, likeuseState:</p><p>✅ <strong>Minimal Re-Renders</strong> → Only updates relevant fields, unlike. useState ✅ <strong>Optimised Performance</strong> → Uses uncontrolled components. ✅ <strong>Simplified Validation</strong> → Built-in support for validation rules. ✅ <strong>Lightweight</strong> → No additional dependencies like Formik.</p><h3>Implementing React Hook Form in React Native</h3><p>First, install:react-hook-form</p><pre>npm install react-hook-form</pre><p>Here’s a simple login form using <strong>React Hook Form</strong>:</p><pre>import React from &#39;react&#39;;<br>import {Text, TextInput, View} from &#39;react-native&#39;;<br>import {useForm, Controller} from &#39;react-hook-form&#39;;<br>import styles from &#39;./styles&#39;;<br>import {Button} from &#39;..&#39;;<br><br>type LoginFormData = {<br>  email: string;<br>  password: string;<br>  isSavePasswordEnable: boolean;<br>};<br>const LoginForm = () =&gt; {<br>  const {<br>    control,<br>    handleSubmit,<br>    formState: {isValid},<br>  } = useForm&lt;LoginFormData&gt;({<br>    defaultValues: {<br>      email: &#39;&#39;,<br>      password: &#39;&#39;,<br>      isSavePasswordEnable: false,<br>    },<br>    mode: &#39;onChange&#39;,<br>    reValidateMode: &#39;onChange&#39;,<br>  });<br>  console.log(&#39;isValid&#39;, isValid);<br><br>  const onSubmit = () =&gt; {};<br>  return (<br>    &lt;View style={styles.container}&gt;<br>      &lt;Text style={styles.welcomeMessage}&gt;Welcome to React Native &lt;/Text&gt;<br>      &lt;Controller<br>        control={control}<br>        rules={{<br>          required: true,<br>          pattern: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/,<br>        }}<br>        render={({field: {onChange, onBlur, value}}) =&gt; (<br>          &lt;TextInput<br>            placeholder=&quot;enter email address *&quot;<br>            style={styles.inputContainer}<br>            onChangeText={onChange}<br>            onBlur={onBlur}<br>            value={value}<br>          /&gt;<br>        )}<br>        name=&quot;email&quot;<br>      /&gt;<br>      &lt;View style={styles.sizeBox12} /&gt;<br>      &lt;Controller<br>        control={control}<br>        rules={{<br>          required: true,<br>          minLength: 5,<br>        }}<br>        render={({field: {onChange, onBlur, value}}) =&gt; (<br>          &lt;TextInput<br>            placeholder=&quot;enter password *&quot;<br>            style={styles.inputContainer}<br>            value={value}<br>            secureTextEntry<br>            onChangeText={onChange}<br>            onBlur={onBlur}<br>          /&gt;<br>        )}<br>        name=&quot;password&quot;<br>      /&gt;<br>      &lt;View style={styles.sizeBox20} /&gt;<br>      &lt;Button<br>        disabled={!isValid}<br>        title=&quot;Login&quot;<br>        onPress={handleSubmit(onSubmit)}<br>      /&gt;<br>    &lt;/View&gt;<br>  );<br>};<br><br>export default LoginForm;</pre><h3>⚡ How React Hook Form Prevents Re-Renders</h3><h3>Uncontrolled Components</h3><p>Unlike,useState RHF <strong>registers inputs as uncontrolled components</strong>, meaning they don’t store their value in state on every keystroke. This reduces unnecessary re-renders.</p><h3>Optimized State Management</h3><p>RHF <strong>only updates the field that changed</strong>, not the entire form. This improves performance by avoiding unnecessary re-renders.</p><h3>Validation Without Re-Renders</h3><p>With mode: &#39;onChange&#39; the field without triggering a full re-render, making the UI more responsive.</p><h3>📌 Example: Compare RHF vs. useState Re-Renders</h3><p>Using useState:</p><pre>const [email, setEmail] = useState(&#39;&#39;);<br>const [password, setPassword] = useState(&#39;&#39;);<br><br>&lt;TextInput value={email} onChangeText={(text) =&gt; setEmail(text)} /&gt;<br>&lt;TextInput value={password} onChangeText={(text) =&gt; setPassword(text)} /&gt;</pre><p>Every keystroke <strong>triggers a full re-render</strong>, which is bad for performance. RHF avoids this.</p><p>With react-hook-form:</p><pre>&lt;Controller<br>  control={control}<br>  render={({ field: { onChange, value } }) =&gt; (<br>    &lt;TextInput value={value} onChangeText={onChange} /&gt;<br>  )}<br>  name=&quot;email&quot;<br>/&gt;</pre><p>Now, React <strong>only updates the specific field</strong>, preventing full re-renders!</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fplayer.vimeo.com%2Fvideo%2F1054447370%3Fh%3Da9ebaa7df5%26app_id%3D122963&amp;dntp=1&amp;display_name=Vimeo&amp;url=https%3A%2F%2Fvimeo.com%2F1054447370%2Fa9ebaa7df5&amp;image=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F1979812722-ed6545a7e7720cebbd11227c228a98bc74798287d83c1aeedbb33eb2b79f6ebe-d_640&amp;type=text%2Fhtml&amp;schema=vimeo" width="750" height="1334" frameborder="0" scrolling="no"><a href="https://medium.com/media/9995aee21a56bef8b30cb4fda385fc50/href">https://medium.com/media/9995aee21a56bef8b30cb4fda385fc50/href</a></iframe><h3>🎯 Key Takeaways</h3><p>✅ <strong>React Hook Form is more efficient than useState for forms.</strong><br>✅ <strong>Prevents unnecessary re-renders by using uncontrolled components.</strong><br>✅ <strong>Validates inputs efficiently without extra renders.</strong><br>✅ <strong>Improves app performance, especially in large forms.</strong></p><p>Using React Hook Form in your React Native apps <strong>leads to a better user experience</strong> by ensuring smooth, lag-free form interactions. Try it out and see the difference! 🚀</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=623ab9e19f3b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Unlocking the Power of React Native Context Providers for Global State]]></title>
            <link>https://medium.com/@dheeraj.bartwal91/unlocking-the-power-of-react-native-context-providers-for-global-state-9e9fc2bb9cf1?source=rss-4972a447592------2</link>
            <guid isPermaLink="false">https://medium.com/p/9e9fc2bb9cf1</guid>
            <category><![CDATA[react-state-management]]></category>
            <category><![CDATA[state-management]]></category>
            <category><![CDATA[react-native]]></category>
            <category><![CDATA[context-api]]></category>
            <category><![CDATA[react]]></category>
            <dc:creator><![CDATA[Dheeraj Bartwal]]></dc:creator>
            <pubDate>Sat, 11 Jan 2025 14:52:39 GMT</pubDate>
            <atom:updated>2025-01-11T14:52:39.885Z</atom:updated>
            <content:encoded><![CDATA[<p>Context provides a way to pass data through the component tree without having to pass props down manually at every level. In a typical React application, data is passed from parent components to child components using <strong>props</strong>. While this works well in many cases, it can lead to a common problem known as <strong>“prop drilling.”</strong></p><h3>What is Prop Drilling?</h3><p>Props drilling occurs when you pass data or functions from a parent component down through several layers of child components, even if the intermediate components don’t need or use that data.</p><pre>import React, { useState } from &#39;react&#39;;<br>import {View} from &#39;react-native&#39;;<br>import Child from &#39;./Child&#39;;<br><br>const Parent = () =&gt; {<br>  const [user, setUser] = useState(&#39;John Doe&#39;);<br>  <br>  return (<br>    &lt;View&gt;<br>      &lt;Child user={user} /&gt;<br>    &lt;/View&gt;<br>  );<br>};<br><br>// Child.js<br>import React from &#39;react&#39;;<br>import {View} from &#39;react-native&#39;;<br>import Grandchild from &#39;./Grandchild&#39;;<br><br>const Child = ({ user }) =&gt; {<br>  return (<br>    &lt;View&gt;<br>      &lt;Grandchild user={user} /&gt;<br>    &lt;/View&gt;<br>  );<br>};<br><br>// Grandchild.js<br>import React from &#39;react&#39;;<br>import {View,Text} from &#39;react-native&#39;;<br><br>const Grandchild = ({ user }) =&gt; {<br>  return &lt;View&gt;<br>          &lt;Text&gt;Hello, {user} &lt;/Text&gt;<br>         &lt;/View&gt;;<br>};<br><br>export default Grandchild;</pre><p>In this example, the user state in the Parent component is passed down to Grandchild, but it goes through the Child component without being used there. This is an example of <strong>prop drilling</strong>.</p><blockquote>The <strong>React Context API </strong>solves this problem: <strong>prop drilling</strong>. It allows you to share state across components without manually passing props down every level of the component tree.</blockquote><p><strong>Create</strong> <strong>Context</strong></p><pre>import React, {createContext, useState} from &#39;react&#39;;<br><br>type ThemeMode = &#39;light&#39; | &#39;dark&#39;;<br><br>interface IThemeContext {<br>  theme: ThemeMode;<br>  setTheme: React.Dispatch&lt;React.SetStateAction&lt;IThemeContext[&#39;theme&#39;]&gt;&gt;;<br>}<br><br>const ThemeContext = createContext&lt;IThemeContext | null&gt;(null);</pre><ul><li>createContext is used to create a <strong>context</strong> for managing the theme in the application.</li><li>The context is initialized with null because by default, the context value is null before it’s provided by the ThemeContextProvider.</li><li>IThemeContextis the interface that defines the shape of the context, ensuring that any consumer of the context will expect a theme (which is of type &#39;light&#39; | &#39;dark&#39;) and a setTheme function to update the theme.</li></ul><p><strong>Creating the Context Provider</strong></p><pre>import React, {createContext, useState} from &#39;react&#39;;<br><br>type ThemeMode = &#39;light&#39; | &#39;dark&#39;;<br><br>interface IThemeContext {<br>  theme: ThemeMode;<br>  setTheme: React.Dispatch&lt;React.SetStateAction&lt;IThemeContext[&#39;theme&#39;]&gt;&gt;;<br>}<br><br>const ThemeContext = createContext&lt;IThemeContext | null&gt;(null);<br><br>const ThemeContextProvider = ({children}: React.PropsWithChildren&lt;{}&gt;) =&gt; {<br>  const [theme, setTheme] = useState&lt;IThemeContext[&#39;theme&#39;]&gt;(&#39;light&#39;);<br><br>  return (<br>    &lt;ThemeContext.Provider value={{theme, setTheme}}&gt;<br>      {children}<br>    &lt;/ThemeContext.Provider&gt;<br>  );<br>};</pre><ul><li>ThemeContextProvider is a <strong>React component</strong> that uses useState to manage the theme state.</li><li>The provider provides the theme and setTheme to its child components by passing them as the value prop to the ThemeContext.Provider.</li><li>useState&lt;IThemeContext[&#39;theme&#39;]&gt;(&#39;light&#39;)initializes the theme state to &#39;light&#39;. The type IThemeContext[&#39;theme&#39;] ensures that the theme state only accepts &#39;light&#39; or &#39;dark&#39;.</li></ul><p><strong>Creating</strong> <strong>the</strong> <strong>useContextWrapper</strong> <strong>Hook</strong></p><pre>import React, {useContext} from &#39;react&#39;;<br><br>interface IConfig {<br>  contextName: string;<br>  providerName: string;<br>}<br><br>const useContextWrapper = &lt;T,&gt;(<br>  context: React.Context&lt;T&gt;,<br>  config: IConfig,<br>): T =&gt; {<br>  const contextValue = useContext(context);<br>  const {contextName, providerName} = config;<br><br>  if (!contextValue) {<br>    throw new Error(`${contextName} must be used within a ${providerName}`);<br>  }<br><br>  return contextValue;<br>};<br><br>export {useContextWrapper};</pre><p><strong>Explanation:</strong></p><ol><li><strong>Generics (</strong><strong>&lt;T,&gt;)</strong>: The hook is generic, allowing it to work with any context type. The T represents the type of the context value, ensuring that the type is inferred and checked correctly when you consume the context.</li><li><strong>Error Handling</strong>: The hook ensures that the contextValue is not null. If it is, it throws an error with a helpful message indicating which context and provider were involved. This is useful for debugging when a component is not wrapped in the correct provider.</li></ol><p><strong>Why Do We Need a </strong><strong>useContextWrapper Hook?</strong></p><p>React useContext hook allows you to consume a context value in a component, but if the context is used outside of its corresponding provider, it will return null. This could lead to subtle bugs and crashes in your application.</p><p>The useContextWrapper hook adds an additional layer of safety by throwing an error when a context is consumed outside of its provider, ensuring that your app behaves as expected.</p><p><strong>Use the </strong><strong>useContextWrapper Hook in the </strong><strong>useThemeContext Hook</strong></p><pre>const useThemeContext = () =&gt;<br>  useContextWrapper(ThemeContext, {<br>    contextName: &#39;ThemeContext&#39;,<br>    providerName: &#39;ThemeContextProvider&#39;,<br>  });</pre><ul><li>useThemeContext wraps useContextWrapper to consume the ThemeContext safely.</li><li>The hook will throw an error if it is used outside of ThemeContextProvider.</li></ul><p><strong>Using the </strong><strong>useThemeContext Hook in Component</strong></p><pre>import React from &#39;react&#39;;<br>import { View, Text, Button, StyleSheet } from &#39;react-native&#39;;<br>import { useThemeContext } from &#39;../context/themeContext&#39;;<br><br>const ComponentA = () =&gt; {<br>  const context = useThemeContext();<br><br>  if (!context) return null;<br><br>  const { theme, setTheme } = context;<br><br>  const toggleTheme = () =&gt; {<br>    setTheme(theme === &#39;light&#39; ? &#39;dark&#39; : &#39;light&#39;);<br>  };<br><br>  console.log(`ComponentA rendering...`);<br><br>  return (<br>    &lt;View style={styles.container}&gt;<br>      &lt;Text style={styles.text}&gt;The current theme is {theme}&lt;/Text&gt;<br>      &lt;Button title=&quot;Toggle Theme&quot; onPress={toggleTheme} /&gt;<br>    &lt;/View&gt;<br>  );<br>};<br><br>const styles = StyleSheet.create({<br>  container: {<br>    flex: 1,<br>    justifyContent: &#39;center&#39;,<br>    alignItems: &#39;center&#39;,<br>  },<br>  text: {<br>    fontSize: 18,<br>    marginBottom: 10,<br>  },<br>});<br><br>export default ComponentA;</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/750/1*uEn7PT_qnmaXHIQqWexPsg.gif" /></figure><h3>Conclusion</h3><p>Using React Context for managing global state is an essential pattern in modern React applications. By combining it with TypeScript and a custom useContextWrapper hook, we can make context consumption much safer and prevent common mistakes that lead to runtime errors.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9e9fc2bb9cf1" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Streamlining Salesforce Integration: Building iOS Apps with Forceios and the Salesforce SDK]]></title>
            <link>https://medium.com/@dheeraj.bartwal91/streamlining-salesforce-integration-building-ios-apps-with-forceios-and-the-salesforce-sdk-bb6795a58634?source=rss-4972a447592------2</link>
            <guid isPermaLink="false">https://medium.com/p/bb6795a58634</guid>
            <category><![CDATA[salesforcesdk-ios-demo]]></category>
            <category><![CDATA[salesforce-ios-app]]></category>
            <category><![CDATA[ios-apps-using-forceios]]></category>
            <category><![CDATA[ios-development]]></category>
            <dc:creator><![CDATA[Dheeraj Bartwal]]></dc:creator>
            <pubDate>Mon, 06 Jan 2025 13:11:39 GMT</pubDate>
            <atom:updated>2025-01-09T13:30:12.804Z</atom:updated>
            <content:encoded><![CDATA[<p>Recently, I worked on an iOS Salesforce application with an outdated codebase that was using <strong>SalesforceMobileSDK-iOS version 6.2.0</strong>. Upgrading it to the latest version (<strong>SalesforceMobileSDK-iOS 12.2.0</strong>) presented some challenges, but it also provided valuable insights. In this article, we’ll explore how to create an iOS application using the <strong>Forceios</strong> NPM package.</p><p><strong>Forceios</strong> simplifies the process of integrating iOS mobile apps with the Salesforce Platform by leveraging the power of the Salesforce Mobile SDK for iOS, making it easier for developers to get started.</p><p><strong>iOS Basic Requirements for Mobile SDK Development</strong></p><p>Before diving into the development process, there are a few essential prerequisites. Here’s what you’ll need:</p><p><strong>1. Salesforce Setup:</strong></p><ul><li>A <a href="https://developer.salesforce.com/signup"><strong>Salesforce Developer Edition</strong></a> organization with a <strong>connected app</strong>.<br> This is necessary for authenticating your app with Salesforce and accessing its APIs.</li></ul><p><strong>2. iOS Development Requirements (for Mobile SDK 11.1 and above):</strong></p><ul><li><strong>iOS SDK:</strong></li><li><strong>Deployment Target:</strong> iOS 15 or later</li><li><strong>Base SDK:</strong> iOS 16 or later</li><li><strong>Xcode Version:</strong> Xcode 14 or later<br> <em>(I recommend using the latest version of Xcode to ensure compatibility and access to the newest tools and features.)</em></li></ul><p>These requirements form the foundation for developing iOS applications that integrate seamlessly with Salesforce via the Salesforce Mobile SDK.</p><p><strong>Creating an iOS Application: Two Approaches</strong></p><p>There are two main ways to create an iOS app that integrates with Salesforce:</p><ol><li><strong>Creating iOS Applications Using Forceios</strong></li><li><strong>Creating iOS Applications Manually Using Xcode</strong></li></ol><p>Let’s explore both options.</p><p><strong>1. Creating iOS Applications Using Forceios</strong></p><p>The <strong>Forceios</strong> NPM package simplifies the creation of iOS apps by providing built-in templates for Salesforce integration. Here’s how you can get started:</p><p><strong>Step 1: Install Forceios</strong></p><p>To begin, install the <strong>Forceios</strong> package globally on your macOS machine. Open your terminal and run the following command.</p><pre>sudo npm install forceios -g</pre><p><strong>Step 2: Create Your iOS App</strong></p><p>Once the package is installed, you can create your iOS app using the following command:</p><pre>forceios create [ - apptype=application_type (native_swift or native, leave empty for native_swift)] \<br> - appname=application_name \<br> - packagename=app_package_identifier (e.g., com.mycompany.myapp) \<br> - organization=organization_name \<br>[ - outputdir=output_directory (leave empty for current directory)]</pre><p><strong>Command Breakdown:</strong></p><ul><li>— apptype: Specify the application type. Leave empty for native_swift (default) or choose native for other options.</li><li>— appname: Define the name of your application.</li><li>— packagename: Set the unique package identifier for your app (e.g., com.mycompany.myapp).</li><li>— organization: Enter your organization’s name.</li><li>— outputdir: Optionally specify a directory where the app should be created. Leave empty to use the current directory.</li></ul><p>After running this command, <strong>Forceios</strong> will scaffold a new iOS app preconfigured for Salesforce integration using the Salesforce Mobile SDK.</p><p><strong>2. Creating iOS Applications Manually Using Xcode</strong></p><p>Alternatively, you can manually create an iOS app and integrate the Salesforce Mobile SDK yourself. This method requires more hands-on configuration but offers full flexibility.</p><p><strong>Step-by-Step Guide:</strong></p><ol><li><strong>Create a New Xcode Project:</strong><br>Start by creating a new iOS project in Xcode and choose the appropriate template (e.g., iOS App).</li><li><strong>Install CocoaPods and the Salesforce Mobile SDK:</strong><br>If you haven’t already, install CocoaPods by following the instructions at <a href="https://cocoapods.org/">cocoapods.org</a>.</li><li><strong>Set Up Your Podfile: </strong>In your Xcode project, create or update the <strong>Podfile</strong> to include the Salesforce Mobile SDK. Add the SalesforceMobileSDK-iOS-Specs repo as the source (it should be the first entry in your Podfile):</li></ol><pre>target &#39;YourAppName&#39; do<br>use_frameworks!<br>source &#39;https://github.com/forcedotcom/SalesforceMobileSDK-iOS-Specs.git&#39; # needs to be first<br>source &#39;https://github.com/CocoaPods/Specs.git&#39;<br>pod &#39;SalesforceSDKCore&#39;<br>end</pre><p><strong>Explanation of Pods:</strong></p><ul><li>SalesforceSDKCore: Implements OAuth, passcodes, networking, and REST APIs.</li><li>SmartStore: Provides secure offline storage, dependent on SalesforceSDKCore.</li><li>MobileSync: Implements offline synchronization, dependent on SmartStore.</li><li>SalesforceAnalytics: Tracks usage statistics for the Mobile SDK.</li><li>SalesforceSDKCommon: Includes utilities shared throughout the SDK.</li><li>FMDB: A third-party module used by the SDK for local database storage.</li></ul><p>4. <strong>Install Dependencies:</strong> Run the following command to install the pods:</p><pre>pod install</pre><p>After installation, open the <strong>.xcworkspace</strong> file to work with your project.</p><p>5. <strong>Update AppDelegate File</strong></p><ul><li>Import <strong>MobileSync</strong> and initialize the SDK in your AppDelegate.swift file:</li></ul><pre>import MobileSync<br><br>override init() {<br>        super.init()<br>        MobileSyncSDKManager.initializeSDK()<br>     }</pre><p>6.<strong> Update SceneDelegate File</strong></p><ul><li>You will also need to update your <strong>SceneDelegate.swift</strong> to handle the app’s lifecycle and authentication flows, especially if you’re using QR-based login or deep linking.</li></ul><pre>import UIKit<br>import SwiftUI<br>import MobileSync<br>import SalesforceSDKCore<br><br>class SceneDelegate: UIResponder, UIWindowSceneDelegate {<br><br>    var window: UIWindow?<br>    <br>    // MARK: - UISceneDelegate Implementation<br>    <br>    func scene(_ scene: UIScene,<br>               openURLContexts urlContexts: Set&lt;UIOpenURLContext&gt;)<br>    {<br>  <br>        // Uncomment when enabling log in via Salesforce UI Bridge API generated QR codes.<br>        /*<br>         * Note: The app&#39;s Info.plist must be updated with the URL type, scheme<br>         * and any other desired options to support custom URL scheme deep links<br>         * for the QR login code.  It is possible to use universal links for<br>         * this also so long as the app is configured, the UI bridge API<br>         * parameters are obtained and passed to<br>         * LoginTypeSelectionViewController.loginWithFrontdoorBridgeUrl<br>         */<br>//        // When the app process was running and receives a custom URL scheme deep link, use login QR code if applicable.<br>//        if let urlContext = urlContexts.first {<br>//            useQrCodeLogInUrl(urlContext.url)<br>//        }<br>    }<br>    <br>    func scene(_ scene: UIScene,<br>               willConnectTo session: UISceneSession,<br>               options connectionOptions: UIScene.ConnectionOptions)<br>    {<br>        guard let windowScene = (scene as? UIWindowScene) else { return }<br>        self.window = UIWindow(frame: windowScene.coordinateSpace.bounds)<br>        self.window?.windowScene = windowScene<br>       <br>        AuthHelper.registerBlock(forCurrentUserChangeNotifications: {<br>           self.resetViewState {<br>               self.setupRootViewController()<br>           }<br>        })<br>        <br>        // Uncomment when enabling log in via Salesforce UI Bridge API generated QR codes.<br>        // When the app process was not running and receives a custom URL scheme deep link, use login QR code if applicable.<br>//        if let urlContext = connectionOptions.urlContexts.first {<br>//            useQrCodeLogInUrl(urlContext.url)<br>//        }<br>    }<br><br>    func sceneDidDisconnect(_ scene: UIScene) {<br>        // Called as the scene is being released by the system.<br>        // This occurs shortly after the scene enters the background, or when its session is discarded.<br>        // Release any resources associated with this scene that can be re-created the next time the scene connects.<br>        // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).<br>    }<br><br>    func sceneDidBecomeActive(_ scene: UIScene) {<br>        // Called when the scene has moved from an inactive state to an active state.<br>        // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.<br>    }<br><br>    func sceneWillResignActive(_ scene: UIScene) {<br>        // Called when the scene will move from an active state to an inactive state.<br>        // This may occur due to temporary interruptions (ex. an incoming phone call).<br>    }<br><br>    func sceneWillEnterForeground(_ scene: UIScene) {<br>        // Called as the scene transitions from the background to the foreground.<br>        // Use this method to undo the changes made on entering the background.<br>        self.initializeAppViewState()<br>        AuthHelper.loginIfRequired {<br>            self.setupRootViewController()<br>        }<br>    }<br><br>    func sceneDidEnterBackground(_ scene: UIScene) {<br>        // Called as the scene transitions from the foreground to the background.<br>        // Use this method to save data, release shared resources, and store enough scene-specific state information<br>        // to restore the scene back to its current state.<br>    }<br>    <br>    // MARK: - Private Methods<br>    <br>   func initializeAppViewState() {<br>       if (!Thread.isMainThread) {<br>           DispatchQueue.main.async {<br>               self.initializeAppViewState()<br>           }<br>           return<br>       }<br>       <br>       self.window?.rootViewController = InitialViewController(nibName: nil, bundle: nil)<br>       self.window?.makeKeyAndVisible()<br>   }<br>   <br>   func setupRootViewController() {<br>       // Setup store based on config userstore.json<br>       MobileSyncSDKManager.shared.setupUserStoreFromDefaultConfig()<br>       // Setup syncs based on config usersyncs.json<br>       MobileSyncSDKManager.shared.setupUserSyncsFromDefaultConfig()<br>    <br>       self.window?.rootViewController = UIHostingController(<br>           rootView: AccountsListView()<br>       )<br>   }<br>   <br>   func resetViewState(_ postResetBlock: @escaping () -&gt; ()) {<br>       if let rootViewController = self.window?.rootViewController {<br>           if let _ = rootViewController.presentedViewController {<br>               rootViewController.dismiss(animated: false, completion: postResetBlock)<br>               return<br>           }<br>       }<br>       postResetBlock()<br>   }<br>    <br>    <br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9xoekTdh508nIYjkexQm6w.png" /></figure><p><strong>Conclusion</strong></p><p>Both <strong>Forceios</strong> and the manual Xcode setup offer powerful solutions for building iOS apps that integrate with Salesforce. While <strong>Forceios</strong> provides a quicker, templated approach to app creation, the manual method gives you full control over your project and its configuration.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bb6795a58634" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Understanding Compound Components in React Native (Part2): A Powerful Pattern for Building Flexible…]]></title>
            <link>https://medium.com/@dheeraj.bartwal91/understanding-compound-components-in-react-native-part2-a-powerful-pattern-for-building-flexible-1347e24d7daa?source=rss-4972a447592------2</link>
            <guid isPermaLink="false">https://medium.com/p/1347e24d7daa</guid>
            <category><![CDATA[reactnative-app]]></category>
            <category><![CDATA[react-native-development]]></category>
            <category><![CDATA[react-native-tutorial]]></category>
            <category><![CDATA[compound-components]]></category>
            <dc:creator><![CDATA[Dheeraj Bartwal]]></dc:creator>
            <pubDate>Thu, 28 Nov 2024 14:18:00 GMT</pubDate>
            <atom:updated>2024-11-28T14:18:00.969Z</atom:updated>
            <content:encoded><![CDATA[<h3>Understanding Compound Components in React Native (Part2): A Powerful Pattern for Building Flexible UIs</h3><p>In modern React development, one of the design patterns that stands out for creating flexible and composable UIs is the <strong>Compound Component Pattern</strong>. This pattern helps you manage a group of components that are logically related but still need to have distinct, reusable pieces of functionality. In this article, we’ll break down how the <strong>Compound Component Pattern</strong> is applied in a React Native application by walking through an example of a <strong>Card Component</strong> with <strong>Header</strong>, <strong>Content</strong>, and <strong>Footer</strong> subcomponents.</p><h4>What is the Compound Component Pattern?</h4><p>The Compound Component Pattern is a way to design components that are loosely coupled but still work together as a cohesive whole. Instead of passing a ton of props down the component tree, the parent component manages the shared logic, while the child components focus on their independent concerns.</p><p>In this article, we’ll take a look at how the Compound Component Pattern is implemented using a simple Card component structure in React Native.</p><p>Let’s dive into the code, which demonstrates how the compound pattern is applied to a Card component.</p><h4>1. The Card Component: The Parent</h4><pre>const Card: ICardComponent = ({children, style}) =&gt; {<br>  return &lt;View style={[style, styles.card]}&gt;{children}&lt;/View&gt;;<br>};</pre><p>In this example, the Card component serves as the parent container for the subcomponents. It accepts children as a prop, which means any components passed inside the &lt;Card&gt;&lt;/Card&gt; wrapper will be rendered here. The style prop allows for customization, and the card itself is styled using styles.card.</p><p>Notice that the Card component defines three subcomponents: Header, Content, and Footer. These are nested within the parent Card component, which allows us to compose the final UI in a structured and flexible way.</p><h4>2. Subcomponents: Header, Content, and Footer</h4><p>The power of the Compound Pattern comes from how we can define components that can work together, while still maintaining individual behavior. In this case, the Header, Content, and Footer are all defined as separate components but are tightly coupled with the Card.</p><pre>Card.Header = ({children, style}: IHeader) =&gt; {<br>  return &lt;View style={[style]}&gt;{children}&lt;/View&gt;;<br>};<br><br>Card.Content = ({children, style}: IContent) =&gt; {<br>  return &lt;View style={[style]}&gt;{children}&lt;/View&gt;;<br>};<br><br>Card.Footer = ({children, style}: IFooter) =&gt; {<br>  return &lt;View style={[style]}&gt;{children}&lt;/View&gt;;<br>};</pre><p>These components are designed to be used as direct children of the Card component, and each one can accept its own children and style.</p><ul><li><strong>Card.Header</strong> can be used to render the header content of the card.</li><li><strong>Card.Content</strong> holds the body of the card, where the main content goes.</li><li><strong>Card.Footer</strong> provides a footer area, typically for actions or additional details.</li></ul><h4>3. The App Component: Composing the Card</h4><p>Now, let’s look at how we can compose these components in the App component.</p><pre>import React from &#39;react&#39;;<br>import {StyleSheet, Text, View, ScrollView, SafeAreaView} from &#39;react-native&#39;;<br>import Switch from &#39;./src/componant/switch&#39;;<br>import Card from &#39;./src/componant/card&#39;;<br>import {Header} from &#39;./src/componant/card/header&#39;;<br>import {Content} from &#39;./src/componant/card/content&#39;;<br>import {Footer} from &#39;./src/componant/card/footer&#39;;<br><br>const App = (): React.JSX.Element =&gt; {<br>  return (<br>    // SafeAreaView to ensure UI is inside the safe area<br>    &lt;SafeAreaView style={style.container}&gt;<br>      &lt;ScrollView<br>        showsVerticalScrollIndicator={false}<br>        contentContainerStyle={style.root}&gt;<br>        {/* Card Component with Header, Content, and Footer */}<br>        &lt;Card&gt;<br>          &lt;Card.Header&gt;<br>            &lt;Header /&gt;<br>          &lt;/Card.Header&gt;<br>          &lt;Card.Content&gt;<br>            &lt;Content /&gt;<br>          &lt;/Card.Content&gt;<br>          &lt;Card.Footer&gt;<br>            &lt;Footer /&gt;<br>          &lt;/Card.Footer&gt;<br>        &lt;/Card&gt;<br>      &lt;/ScrollView&gt;<br>    &lt;/SafeAreaView&gt;<br>  );<br>};<br><br>export default App;<br><br>const style = StyleSheet.create({<br>  container: {<br>    flex: 1,<br>  },<br>  root: {<br>    flexGrow: 1,<br>    alignItems: &#39;center&#39;,<br>    paddingBottom: 20,<br>  },<br>  switchContainer: {<br>    alignItems: &#39;center&#39;,<br>    width: &#39;100%&#39;,<br>    paddingTop: 20,<br>  },<br>  spacer: {<br>    height: 20,<br>  },<br>});</pre><p>Here, we’re composing the Card component by passing in the Header, Content, and Footer as its children. Each of these child components is defined separately, but they are now part of the Card structure, thanks to the compound pattern.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/750/1*IuA3TvV9UTA_ROr-pg9ojQ.png" /></figure><h3>Benefits of Using the Compound Pattern</h3><ul><li><strong>Readability</strong>: The code becomes easier to read because the Card component encapsulates the layout logic, and the child components (Header, Content, Footer) focus only on their content.</li><li><strong>Maintainability</strong>: If you need to make changes to the layout or shared logic, you can do so in the parent Card component without modifying each individual child.</li><li><strong>Separation of Concerns</strong>: Each component (parent and child) has a clear responsibility, making the codebase easier to manage and extend.</li></ul><h3>Reusability and Dynamic Composition in the Compound Pattern</h3><p>One of the key advantages of using the <strong>Compound Component Pattern</strong> is the flexibility and reusability it brings to your components. In this implementation, each child component — Header, Content, and Footer—is decoupled from the Card component, meaning that you can easily reuse these components in different places across your app, either inside or outside of a Card.</p><h4>Reusable Child Components</h4><p>Since the Header, Content, and Footer components are separate and self-contained, you can use them independently throughout your application. For example, you might use the Header component in one part of your app to display a title, and the Footer in another part for actions or information. These components can be used without being wrapped by the Card, allowing for greater flexibility in your UI design.</p><h4>Dynamic Composition for Greater Flexibility</h4><p>What’s even more powerful is that the Card component itself can be reused across various parts of your app. You can pass different combinations of Header, Content, and Footer to create unique card layouts as needed. This dynamic composition makes the Card component incredibly versatile and reusable.</p><p>For instance, you might create one Card with a custom Header, Content, and Footer for a user profile screen, and another Card with a different Header, Content, and Footer for a product detail page, all by simply passing different content into the same Card wrapper.</p><p>Here’s an example:</p><pre>&lt;Card&gt;<br>  &lt;Card.Header&gt;<br>    &lt;Text&gt;User Profile&lt;/Text&gt;<br>  &lt;/Card.Header&gt;<br>  &lt;Card.Content&gt;<br>    &lt;Text&gt;John Doe&lt;/Text&gt;<br>    &lt;Text&gt;Age: 30&lt;/Text&gt;<br>  &lt;/Card.Content&gt;<br>  &lt;Card.Footer&gt;<br>    &lt;Button title=&quot;Edit Profile&quot; /&gt;<br>  &lt;/Card.Footer&gt;<br>&lt;/Card&gt;</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/750/1*spKW4y2hB7thsbkW83uTnA.png" /></figure><h3>Conclusion</h3><p>The <strong>Compound Component Pattern</strong> allows for a high degree of flexibility in building reusable components. By decoupling the Header, Content, and Footer from the Card, we can use each of them independently in other parts of the app, or compose them dynamically in different contexts.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1347e24d7daa" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Understanding Compound Components in React (Part1): A Powerful Pattern for Building Flexible UIs]]></title>
            <link>https://medium.com/@dheeraj.bartwal91/understanding-compound-components-in-react-a-powerful-pattern-for-building-flexible-uis-068f564e91b8?source=rss-4972a447592------2</link>
            <guid isPermaLink="false">https://medium.com/p/068f564e91b8</guid>
            <category><![CDATA[react-native]]></category>
            <category><![CDATA[toggle-button]]></category>
            <category><![CDATA[compound-components]]></category>
            <dc:creator><![CDATA[Dheeraj Bartwal]]></dc:creator>
            <pubDate>Wed, 27 Nov 2024 07:32:14 GMT</pubDate>
            <atom:updated>2024-11-28T14:18:40.454Z</atom:updated>
            <content:encoded><![CDATA[<p>The Compound Component Pattern allows you to write a components that all work together to perform a task. In other words compound components refer to a pattern where a component is split into multiple smaller subcomponents that work together as a unit. The idea is to provide a clean and flexible interface for the user while maintaining separation of concerns between the different parts of the component. Compound components are typically composed of a parent component and a set of nested child components that communicate with each other via <strong>context</strong> or <strong>props</strong>.</p><p>This pattern is especially useful when the child components need to be tightly coupled but still remain decoupled from the parent component’s internal logic. With compound components, the parent component manages the state, and the child components consume this state through context or props, resulting in a highly flexible and customizable system.</p><h3>How Compound Components Work: A Practical Example</h3><p>In this article I’ll teach you how to write a component using compound component pattern.</p><h4>Step 1: Define the Parent Component (Switch)</h4><pre>import React, {createContext, useContext, useState} from &#39;react&#39;;<br>import {View, Text, TouchableOpacity} from &#39;react-native&#39;;<br>import styles from &#39;./styles&#39;;<br><br>interface ISwitchContext {<br>  isChecked: boolean;<br>  toggle: () =&gt; void;<br>}<br>const SwitchContext = createContext&lt;ISwitchContext | null&gt;(null);<br><br>interface ISwitch {<br>  children: React.ReactNode;<br>  check?: boolean;<br>}<br><br>interface ISwitchComponent extends React.FC&lt;ISwitch&gt; {<br>  Label: React.FC&lt;{children: React.ReactNode}&gt;;<br>  Button: React.FC;<br>}<br><br>const Switch: ISwitchComponent = ({children, check = false}) =&gt; {<br>  const [isChecked, setIsChecked] = useState&lt;boolean&gt;(check);<br><br>  const toggle = () =&gt; {<br>    setIsChecked(pre =&gt; !pre);<br>  };<br><br>  return (<br>    &lt;SwitchContext.Provider value={{isChecked, toggle}}&gt;<br>      &lt;View style={styles.container}&gt;{children}&lt;/View&gt;<br>    &lt;/SwitchContext.Provider&gt;<br>  );<br>};</pre><h4>Step 2: Define the Child Components (Switch.Label and Switch.Button)</h4><p>Now, we define the child components, Switch.Label and Switch.Button. These components will consume the state provided by the parent (Switch) via context.</p><pre>Switch.Label = ({children}: {children: React.ReactNode}) =&gt; {<br>  return &lt;Text style={styles.label}&gt;{children}&lt;/Text&gt;;<br>};<br><br>Switch.Button = () =&gt; {<br>  const context = useContext(SwitchContext);<br><br>  if (!context) {<br>    throw new Error(&#39;Switch.Button must be used within a Switch component&#39;);<br>  }<br><br>  const {isChecked, toggle} = context;<br><br>  return (<br>    &lt;TouchableOpacity style={styles.button} onPress={toggle}&gt;<br>      &lt;Text style={styles.buttonText}&gt;{isChecked ? &#39;ON&#39; : &#39;OFF&#39;}&lt;/Text&gt;<br>    &lt;/TouchableOpacity&gt;<br>  );<br>};<br><br>export default Switch;</pre><h4>Step 3: Use the Compound Components</h4><p>Now, we can use the Switch component along with its subcomponents (Switch.Label and Switch.Button) in the parent component:</p><pre>import React from &#39;react&#39;;<br>import {StyleSheet, View} from &#39;react-native&#39;;<br>import Switch from &#39;./src/componant/switch&#39;;<br><br>const App = (): React.JSX.Element =&gt; {<br>  return (<br>    &lt;View style={style.root}&gt;<br>      &lt;Switch&gt;<br>        &lt;Switch.Label&gt;Push Notification Enabled&lt;/Switch.Label&gt;<br>        &lt;Switch.Button /&gt;<br>      &lt;/Switch&gt;<br>      &lt;View style={style.spacer} /&gt;<br>      &lt;Switch check={true}&gt;<br>        &lt;Switch.Label&gt;Enable Dark Mode&lt;/Switch.Label&gt;<br>        &lt;Switch.Button /&gt;<br>      &lt;/Switch&gt;<br>      &lt;View style={style.spacer} /&gt;<br>      &lt;Switch check={true}&gt;<br>        &lt;Switch.Label&gt;Enable Auto Synce&lt;/Switch.Label&gt;<br>        &lt;Switch.Button /&gt;<br>      &lt;/Switch&gt;<br>    &lt;/View&gt;<br>  );<br>};<br><br>export default App;<br><br>const style = StyleSheet.create({<br>  root: {<br>    flex: 1,<br>    justifyContent: &#39;center&#39;,<br>    alignItems: &#39;center&#39;,<br>  },<br>  spacer: {<br>    height: 50,<br>  },<br>});</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/750/1*80QU7WRLX27ERarqUO613A.png" /></figure><h3>How It Works:</h3><ul><li>The Switch component provides the state (isChecked) and the toggle function via SwitchContext.Provider.</li><li>The Switch.Label component simply displays the text passed to it, while the Switch.Button component reads the state from the context and toggles the state when clicked.</li><li>The Switch.Button renders either &quot;ON&quot; or &quot;OFF&quot; based on the isChecked state.</li></ul><p>This pattern is extremely flexible because the consumer can customize the rendering of Switch.Label and Switch.Button without worrying about the internal state management or logic.</p><h3>Conclusion</h3><p>The compound component pattern in React is a powerful way to build flexible, reusable, and maintainable UIs. By using context and breaking down a component into smaller, composable parts, you can create complex interfaces that are both customizable and easy to manage.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=068f564e91b8" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Simplifying API Requests in React Native with Axios: A Flexible Client for GET and POST Requests]]></title>
            <link>https://medium.com/@dheeraj.bartwal91/simplifying-api-requests-in-react-native-with-axios-a-flexible-client-for-get-and-post-requests-48f93bc90fac?source=rss-4972a447592------2</link>
            <guid isPermaLink="false">https://medium.com/p/48f93bc90fac</guid>
            <category><![CDATA[react-native]]></category>
            <category><![CDATA[axios]]></category>
            <category><![CDATA[api-integration]]></category>
            <category><![CDATA[react]]></category>
            <dc:creator><![CDATA[Dheeraj Bartwal]]></dc:creator>
            <pubDate>Tue, 26 Nov 2024 08:20:06 GMT</pubDate>
            <atom:updated>2024-11-26T08:20:06.185Z</atom:updated>
            <content:encoded><![CDATA[<p>In modern mobile application development, making HTTP requests is a fundamental part of any app that communicates with the backend server. Whether you are fetching data from a server or sending user input to a backend, making HTTP requests is an everyday task. If it is not done carefully, this can lead to repetitive and error-prone code. In this post, I will show you how to build a reusable and flexible API client in React Native using Axios.</p><h3>Why Use a Custom API Client?</h3><p>React native application often require making API requests to fetch data or send updates. Using Axis makes this process easier due to its simplicity and powerful features, such as automatic JSON parsing, built-in request/response interception, and promise-based syntax.However, when your application grows, it’s easy to get stuck with redundant code for every single API call. A custom API client allows you to:</p><ul><li><strong>Centralize logic</strong>: Manage headers, authentication, timeouts, and error handling in one place.</li><li><strong>Simplify requests</strong>: Abstract HTTP methods (GET, POST, etc.) into reusable functions.</li><li><strong>Improve maintainability</strong>: Keep your code DRY and easier to maintain as your app scales.</li></ul><h3>Step 1: Setting Up the ApiClient Class</h3><p>To start, let’s create the ApiClient class, which will handle Axios requests. This class will be responsible for managing common configurations like the base URL, headers, and request timeouts.</p><pre>import axios, { AxiosInstance, AxiosResponse } from &#39;axios&#39;;<br><br>export interface ApiPayload&lt;K&gt; {<br>  payload?: K;<br>}<br><br>class ApiClient {<br>  private readonly axiosInstance: AxiosInstance;<br>  private readonly axiosHeaders = {<br>    Accept: &#39;application/json&#39;,<br>    &#39;Content-Type&#39;: &#39;application/json&#39;,<br>  };<br><br>  constructor() {<br>    this.axiosInstance = axios.create({<br>      baseURL: &#39;https://jsonplaceholder.typicode.com&#39;,  // Base URL for JSONPlaceholder (can be replaced)<br>      headers: this.axiosHeaders,<br>      timeout: 10000,  // Timeout for requests<br>      timeoutErrorMessage: &#39;Slow Network&#39;,  // Custom error message for slow requests<br>      validateStatus(status: number) {<br>        return (status &gt;= 200 &amp;&amp; status &lt; 300) || status === 400 || status === 401;  // Status codes validation<br>      },<br>    });<br>  }<br><br>  requestHeader = () =&gt; {<br>    return {<br>      Authorization: &#39;Bearer YOUR_TOKEN&#39;,  // Authorization token (can be updated dynamically)<br>    };<br>  };<br><br>  handleBodyResponse = async &lt;K&gt;(response: AxiosResponse): Promise&lt;K&gt; =&gt; {<br>    const { status, data, statusText } = response;<br>    if (status === 200) return Promise.resolve(data);<br>    const errorMessage = status === 401 ? &#39;Unauthorized&#39; : statusText;<br>    return Promise.reject({ message: errorMessage });<br>  };<br><br>  postApiService = async &lt;K, T&gt;(api: string, reqParam: ApiPayload&lt;K&gt;): Promise&lt;T&gt; =&gt; {<br>    try {<br>      const response = await this.axiosInstance.post&lt;T&gt;(api, reqParam, {<br>        headers: { ...this.axiosHeaders, ...this.requestHeader() },<br>      });<br>      return this.handleBodyResponse(response);<br>    } catch (error) {<br>      console.error(&#39;Error in postApiService:&#39;, error);<br>      throw error;<br>    }<br>  };<br><br>  getApiService = async &lt;K&gt;(api: string): Promise&lt;K&gt; =&gt; {<br>    try {<br>      const response = await this.axiosInstance.get&lt;K&gt;(api, {<br>        headers: { ...this.axiosHeaders, ...this.requestHeader() },<br>      });<br>      return this.handleBodyResponse(response);<br>    } catch (error) {<br>      console.error(&#39;Error in getApiService:&#39;, error);<br>      throw error;<br>    }<br>  };<br>}<br><br>export const API = new ApiClient();</pre><h3>Step 2: Creating a Flexible Service Handler for API Calls</h3><p>Next, we need to create a generalized serviceHandler function. This function will manage different HTTP methods (such as GET and POST) and make it easier to interact with the ApiClient.</p><p>The goal here is to abstract the repetitive logic and provide a simple interface for making API requests.</p><pre>import { API, ApiPayload } from &#39;./apiClient&#39;;<br><br>export enum API_METHOD {<br>  POST = &#39;POST&#39;,<br>  GET = &#39;GET&#39;,<br>}<br><br>export const serviceHandler = async &lt;K, T&gt;(<br>  method: API_METHOD,<br>  url: string,<br>  payload?: K,<br>): Promise&lt;T&gt; =&gt; {<br>  try {<br>    switch (method) {<br>      case API_METHOD.GET:<br>        const getResponse = await API.getApiService&lt;T&gt;(url);<br>        return getResponse;<br><br>      case API_METHOD.POST:<br>        const postResponse = await API.postApiService&lt;K, T&gt;(<br>          url,<br>          payload ? { payload } : ({} as ApiPayload&lt;K&gt;),<br>        );<br>        return postResponse;<br><br>      default:<br>        throw new Error(`Unsupported HTTP method: ${method}`);<br>    }<br>  } catch (error) {<br>    console.error(&#39;Error in serviceHandler:&#39;, error);<br>    throw error;<br>  }<br>};</pre><h3>Step 3: Using the serviceHandler for API Calls in React Native</h3><p>Now that we have both the ApiClient and serviceHandler, making API requests in React Native becomes simple and clean.</p><h4>Sending Data to an API (POST)</h4><pre>interface CreateUserPayload {<br>  name: string;<br>}<br><br>const createUser = async (newUser: CreateUserPayload) =&gt; {<br>  try {<br>    const createdUser = await serviceHandler&lt;CreateUserPayload, User&gt;(<br>      API_METHOD.POST,<br>      &#39;/users&#39;,<br>      newUser<br>    );<br>    console.log(&#39;Created User:&#39;, createdUser);<br>  } catch (error) {<br>    console.error(&#39;Error creating user:&#39;, error);<br>  }<br>};</pre><h4>Fetching Data from an API (GET)</h4><pre>import { API_METHOD, serviceHandler } from &#39;./serviceHandler&#39;; <br><br>// Define the Article interface based on the expected response structure<br>interface Article {<br>  id: number;<br>  title: string;<br>  content: string;<br>  author: string;<br>  publicationDate: string;<br>}<br><br>// Function to get a Medium article by its ID<br>const getMediumArticle = async (articleId: number): Promise&lt;Article | void&gt; =&gt; {<br>  try {<br>    const article = await serviceHandler&lt;null, Article&gt;(<br>      API_METHOD.GET,<br>      `/articles/${articleId}` <br>    );<br>    console.log(&#39;Fetched Article:&#39;, article);<br>    return article;<br> } catch (error) {<br>    console.error(&#39;Error fetching article:&#39;, error);<br>  }<br>};</pre><h3>Conclusion</h3><p>By leveraging TypeScript’s features like interfaces, generics, and enums, we can ensure that our code is both scalable and easy to maintain, especially as the complexity of the application grows. Whether you’re working with user creation, fetching articles, or any other API interaction, using a consistent service handler pattern simplifies the process, allowing you to focus on building features rather than managing repetitive HTTP logic.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=48f93bc90fac" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Offline Synchronization in React Native: Managing Client Data with Local Flags.]]></title>
            <link>https://medium.com/@dheeraj.bartwal91/offline-synchronization-in-react-native-managing-client-data-with-local-flags-ea446a7ad084?source=rss-4972a447592------2</link>
            <guid isPermaLink="false">https://medium.com/p/ea446a7ad084</guid>
            <category><![CDATA[offline-storage]]></category>
            <category><![CDATA[sqlite]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[react-native]]></category>
            <dc:creator><![CDATA[Dheeraj Bartwal]]></dc:creator>
            <pubDate>Thu, 07 Nov 2024 13:17:26 GMT</pubDate>
            <atom:updated>2024-11-07T13:17:26.005Z</atom:updated>
            <content:encoded><![CDATA[<p>Offline functionality is essential for modern mobile apps, especially when network connectivity is unreliable or intermittent. Building an app that works seamlessly both online and offline can be challenging, but with the right tools and strategies, you can create a seamless experience for users who need it even when they’re not connected to the internet. Needed to interact with your app.</p><p>In this article, we will explore how to handle <strong>offline synchronization</strong> in a React Native app using a flag-based approach similar to how Salesforce handles data sync. By marking client data with specific flags like local, locally_created, locally_updated, and locally_deleted, you can track the state of each record and sync them with the server when network connectivity is restored.</p><h3>Key Concepts for Offline Synchronization</h3><p>When an app works offline, data changes need to be stored locally. Once the app regains an internet connection, the app must synchronize this local data with the server. A <strong>flagging system</strong> is a simple and efficient way to track the state of each record.</p><p>Let’s break down the flags you’ll use to track the state of each record:</p><ol><li><strong>local</strong>: The record exists locally, but it hasn’t been modified or created while offline.</li><li><strong>locally_created</strong>: The record was created while offline and needs to be synced with the server.</li><li><strong>locally_updated</strong>: The record has been modified while offline and needs to be synced.</li><li><strong>locally_deleted</strong>: The record was deleted locally, and this deletion should be reflected on the server.</li></ol><p>By using these flags, you can ensure that your app knows exactly which records need to be sent to the server when the network is restored.</p><h3>Setting Up the Data Structure</h3><p>Let’s start by defining the structure of the client record created locally in the app’s local storage.</p><h3>Scenario 1: locally_created</h3><pre>{<br>  client_id: 123,<br>  local: true,<br>  locally_created: true,<br>  locally_updated: false,<br>  locally_deleted: false,<br>  last_modified: &#39;2024-11-07T10:00:00Z&#39;,<br>  data: {<br>    name: &quot;John Doe&quot;,<br>    email: &quot;john.doe@example.com&quot;,<br>    phone: &quot;+1 234 567 890&quot;<br>  }<br>}</pre><h3>Explanation :</h3><ul><li><strong>locally_created: true</strong>: This means that this client record has been newly created while the app was offline. Since the app wasn’t connected to the server at the time of creation, it is marked as locally_created. This record has not yet been synced with the server.</li><li><strong>locally_updated: false</strong>: No updates have been made to this client record since it was created.</li><li><strong>locally_deleted: false</strong>: No deletion of the client has been performed.</li><li><strong>local: true</strong>: Flag indicates that the record is available on the device but hasn’t been sent to the server yet.</li></ul><h3>Scenario 2: locally_update</h3><pre>{<br>  client_id: 123,<br>  local: true,<br>  locally_created: false,<br>  locally_updated: true,<br>  locally_deleted: false,<br>  last_modified: &#39;2024-11-07T10:30:00Z&#39;,<br>  data: {<br>    name: &quot;Ron&quot;,<br>    email: &quot;ron@example.com&quot;,<br>    phone: &quot;+1 234 567 891&quot;<br>  }<br>}</pre><h3>Explanation :</h3><ul><li><strong>locally_created: false</strong>: This record was not created locally; it existed previously either on the server or the local database.</li><li><strong>locally_updated: true</strong>: This record has been updated while offline (e.g., the client’s name, email, or phone number has been changed). Since the app was offline at the time, this change is marked as locally_updated.</li><li><strong>locally_deleted: false</strong>: The record has not been marked for deletion.</li><li><strong>local: true</strong>: Flag indicates that the record is available on the device but hasn’t been sent to the server yet.</li></ul><h3>Scenario 3: locally_deleted</h3><pre><br>  client_id: 123,<br>  local: true,<br>  locally_created: false,<br>  locally_updated: false,<br>  locally_deleted: true,<br>  last_modified: &#39;2024-11-07T10:30:00Z&#39;,<br>  data: {<br>    name: &quot;Ron&quot;,<br>    email: &quot;ron@example.com&quot;,<br>    phone: &quot;+1 234 567 891&quot;<br>  }<br>}</pre><h3>Explanation:</h3><ul><li><strong>locally_created: false</strong>: This record was not newly created locally; it existed before the offline session (either on the server or in local storage).</li><li><strong>locally_updated: false</strong>: No updates have been made to this record locally.</li><li><strong>locally_deleted: true</strong>: This record has been marked for deletion locally . This deletion has not yet been reflected on the server, so the record is flagged as locally_deleted.</li><li><strong>local: true</strong>: Flag indicates that the record is available on the device but hasn’t been sent to the server yet.</li></ul><h3>Conflict Resolution</h3><p>While syncing, conflicts can arise (e.g., when a record was modified both locally and remotely). To handle this, you can implement one of these strategies:</p><ol><li><strong>Last Write Wins (LWW)</strong>: Use the last_modified timestamp to determine which version is most recent.</li><li><strong>Merge Changes</strong>: Automatically merge data changes or prompt the user to choose which version to.</li></ol><h3>Conclusion: Ensuring Seamless User Experience with Offline Sync</h3><p>In modern mobile applications, offline-first design is crucial for providing users with a smooth and uninterrupted experience, even when network connectivity is unreliable or unavailable. By leveraging flags like local: true, locally_created, locally_updated, and locally_deleted, we can effectively track the state of each record, ensuring that changes made while offline are properly managed and synchronized with the server when the network is restored.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ea446a7ad084" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Generics in React: Building Reusable Components.]]></title>
            <link>https://medium.com/@dheeraj.bartwal91/generics-in-react-building-reusable-components-389604f98f04?source=rss-4972a447592------2</link>
            <guid isPermaLink="false">https://medium.com/p/389604f98f04</guid>
            <category><![CDATA[react]]></category>
            <category><![CDATA[react-native]]></category>
            <category><![CDATA[typescript]]></category>
            <dc:creator><![CDATA[Dheeraj Bartwal]]></dc:creator>
            <pubDate>Wed, 06 Nov 2024 12:52:00 GMT</pubDate>
            <atom:updated>2024-11-06T12:52:00.988Z</atom:updated>
            <content:encoded><![CDATA[<p>One of the most powerful use cases for generics is in creating flexible, reusable components in <strong>React</strong>. Generics allow you to build components that work with different types of data while ensuring that the data passed to the component is type-safe.</p><h3>A Generic List Component in React</h3><p>Let’s look at a practical example of a generic List component that renders a list of items of any type:</p><pre>import React from &#39;react&#39;;<br>import { View } from &#39;react-native&#39;;<br>import { FooterView, ProtocolItem } from &#39;~components/molecules&#39;;<br>import styles from &#39;./styles&#39;;<br>import Layout from &#39;../Layout&#39;;<br><br>interface ListItem {<br>  id: number;<br>  name: string;<br>  isChecked: boolean;<br>}<br><br>interface ListProps&lt;T extends ListItem&gt; {<br>  items: T[];<br>  renderItem: (item: T) =&gt; React.ReactNode;<br>  handleItemClick: (item: T) =&gt; void;<br>}<br><br>const List = &lt;T extends ListItem&gt;({ items, renderItem, handleItemClick }: ListProps&lt;T&gt;) =&gt; {<br>  const renderListItems = () =&gt; {<br>    return items.map((item) =&gt; (<br>      &lt;ProtocolItem<br>        key={item.id}<br>        Name={item.name}<br>        isChecked={item.isChecked}<br>        onItemClick={() =&gt; handleItemClick(item)} // Pass the correct item on click<br>      /&gt;<br>    ));<br>  };<br><br>  return (<br>    &lt;Layout stickyHeaderIndices={[0]}&gt;<br>      &lt;View style={styles.container}&gt;<br>        &lt;View style={styles.checklistContainer}&gt;<br>          {renderListItems()}<br>        &lt;/View&gt;<br>      &lt;/View&gt;<br>    &lt;/Layout&gt;<br>  );<br>};<br><br>export default List;</pre><h3>Key Points:</h3><ul><li>The List component is a <strong>generic component</strong> that works with any type that extends ListItem.</li><li>We use generics to type the list of items (items: T[]) and the handleItemClick function.</li><li>The renderItem function allows you to render the items in a custom way, while keeping the component flexible and reusable for different types.</li></ul><p>By using generics in this List component, you ensure that it is type-safe and flexible enough to be used with different types of list items.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=389604f98f04" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Mastering Generics in TypeScript: A Complete Guide]]></title>
            <link>https://medium.com/codex/mastering-generics-in-typescript-a-complete-guide-5c09a01d3919?source=rss-4972a447592------2</link>
            <guid isPermaLink="false">https://medium.com/p/5c09a01d3919</guid>
            <category><![CDATA[react]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[react-native]]></category>
            <dc:creator><![CDATA[Dheeraj Bartwal]]></dc:creator>
            <pubDate>Wed, 06 Nov 2024 12:44:44 GMT</pubDate>
            <atom:updated>2024-11-25T12:15:15.288Z</atom:updated>
            <content:encoded><![CDATA[<p>Generics are one of the most powerful features in TypeScript, enabling developers to write flexible, reusable, and type-safe code. If you’ve ever written a function that operates on multiple types of data, but you want to ensure that type safety isn’t compromised, generics are the solution. In this article, we’ll take a deep dive into what generics are, how to use them effectively in TypeScript, and provide real-world examples to help you master them.</p><h3>What Are Generics?</h3><p>Generics in TypeScript allow you to create functions, classes, and interfaces that work with any data type while maintaining full type safety. The benefit of generics is that they provide <strong>reusability</strong> and <strong>flexibility</strong> without losing the power of TypeScript’s static typing system.</p><h3>Basic Syntax of Generics</h3><p>The basic syntax for defining a generic function in TypeScript looks like this:</p><pre>function logValue&lt;T&gt;(arg: T): T {<br>  return arg;<br>}</pre><p>Here:</p><ul><li>T is a placeholder for any type that will be determined at runtime.</li><li>T can be any valid TypeScript type (string, number, boolean, custom interfaces, etc.).</li><li>The function logValue takes an argument arg of type T, and returns a value of type T.</li></ul><h3>Generics with Arrays</h3><p>Generics are particularly useful when working with arrays, collections, or lists of data, allowing you to maintain type safety when you don’t know the specific type in advance.</p><h3>Example 1: Reversing an Array with Generics</h3><pre>function reverse&lt;T&gt;(arr: T[]): T[] {<br>  return arr.reverse();<br>}</pre><pre>const reversedNumbers = reverse([1, 2, 3, 4]);  // Inferred type: number[]<br>const reversedStrings = reverse([&quot;apple&quot;, &quot;banana&quot;, &quot;cherry&quot;]);  // Inferred type: string[]</pre><pre>console.log(reversedNumbers);  // Outputs: [4, 3, 2, 1]<br>console.log(reversedStrings);  // Outputs: [&quot;cherry&quot;, &quot;banana&quot;, &quot;apple&quot;]</pre><p>Here, the function reverse takes an array of type T[] and returns an array of the same type. This ensures that even though the array can contain different types of data, it will always be type-safe.</p><h3>Generics with Interfaces</h3><p>You can also use generics in interfaces to define flexible structures. This allows you to define reusable, type-safe data structures.</p><h3>Example 2: Using Generics in an Interface</h3><pre>interface Box&lt;T&gt; {<br>  value: T;<br>}</pre><pre>const numberBox: Box&lt;number&gt; = { value: 42 };<br>const stringBox: Box&lt;string&gt; = { value: &quot;Hello World&quot; };</pre><pre>console.log(numberBox.value); // Outputs: 42<br>console.log(stringBox.value); // Outputs: Hello World</pre><h3>Example 3: Using Generics in API Responses</h3><pre>interface Response&lt;T&gt; {<br>  status: string;<br>  data: T;<br>}</pre><pre>function doWebRequest&lt;T&gt;(url: string, callback: (result: Response&lt;T&gt;) =&gt; void): void {<br>  const result: Response&lt;T&gt; = {<br>    status: &quot;success&quot;,<br>    data: {} as T,<br>  };<br>  callback(result);<br>}</pre><pre>doApiRequest&lt;number&gt;(&quot;https://api.example.com/number&quot;, (result) =&gt; {<br>  console.log(result.data + 5);  <br>});</pre><pre>doApiRequest&lt;string&gt;(&quot;https://api.example.com/string&quot;, (result) =&gt; {<br>  console.log(result.data.toUpperCase());  <br>});</pre><p>In this example:</p><ul><li>The Response interface is a generic interface that can hold data of any type.</li><li>The doWebRequest function accepts a URL and a callback that expects a Response&lt;T&gt;, where T can be any type.</li></ul><p>By using generics, we ensure type safety, so we don’t have to worry about accidentally trying to add 5 to a string or calling .toUpperCase() on a number.</p><h3>Conclusion</h3><p>Generics in TypeScript offer a robust way to write flexible and reusable code while maintaining strong type safety.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5c09a01d3919" width="1" height="1" alt=""><hr><p><a href="https://medium.com/codex/mastering-generics-in-typescript-a-complete-guide-5c09a01d3919">Mastering Generics in TypeScript: A Complete Guide</a> was originally published in <a href="https://medium.com/codex">CodeX</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>