<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Khánh nguyen</title>
    <description>The latest articles on DEV Community by Khánh nguyen (@khnh_nguyen_49f492436eef).</description>
    <link>https://dev.to/khnh_nguyen_49f492436eef</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2503673%2Fe19b32e5-87b1-4d29-8829-2a36ee4725a2.jpg</url>
      <title>DEV Community: Khánh nguyen</title>
      <link>https://dev.to/khnh_nguyen_49f492436eef</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/khnh_nguyen_49f492436eef"/>
    <language>en</language>
    <item>
      <title>OTA hot update in react native, easy to control with CMS</title>
      <dc:creator>Khánh nguyen</dc:creator>
      <pubDate>Sun, 26 Jan 2025 03:22:22 +0000</pubDate>
      <link>https://dev.to/khnh_nguyen_49f492436eef/ota-hot-update-in-react-native-easy-to-control-with-cms-51ha</link>
      <guid>https://dev.to/khnh_nguyen_49f492436eef/ota-hot-update-in-react-native-easy-to-control-with-cms-51ha</guid>
      <description>&lt;p&gt;In a previous post, I introduced the React Native OTA Hot Update library, which allows you to self-host a backend for managing hot updates. In this guide, I will walk you through creating a custom CMS using Strapi to control versions and manage hot updates for React Native apps.&lt;/p&gt;

&lt;p&gt;Library: &lt;a href="https://github.com/vantuan88291/react-native-ota-hot-update/" rel="noopener noreferrer"&gt;https://github.com/vantuan88291/react-native-ota-hot-update/&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Step 1: Install Strapi
&lt;/h1&gt;

&lt;p&gt;First, install Strapi locally by following the &lt;a href="https://docs.strapi.io/dev-docs/quick-start" rel="noopener noreferrer"&gt;Strapi Quick Start guide&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Step 2: Prepare CMS Structure
&lt;/h1&gt;

&lt;p&gt;To enable OTA updates, design an API in the CMS to filter bundles based on the app version (e.g., 1.0.0, 1.0.1). The app should only receive OTA updates compatible with its version.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;After successfully installing Strapi, log in to the admin dashboard and navigate to &lt;strong&gt;Content-Type Builder&lt;/strong&gt;. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnpkohrqj2l16q7jxy7c9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnpkohrqj2l16q7jxy7c9.png" alt="Image description" width="488" height="950"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a new collection type for managing bundles:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Click &lt;strong&gt;Create new collection type&lt;/strong&gt; under the &lt;strong&gt;Collection types&lt;/strong&gt; section.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo7ffzq2dtiv2yn8jyeq1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo7ffzq2dtiv2yn8jyeq1.png" alt="Image description" width="440" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Name the collection (e.g., &lt;code&gt;android&lt;/code&gt; for Android updates):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyctevta0c1ojkyhy3v6h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyctevta0c1ojkyhy3v6h.png" alt="Image description" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add the following fields to the collection, as shown below:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhm34sbabo26tg3262vh6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhm34sbabo26tg3262vh6.png" alt="Image description" width="800" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Repeat the process to create a collection for iOS.&lt;/li&gt;
&lt;li&gt;Once the collections are created, update their permissions:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Go to &lt;strong&gt;Settings&lt;/strong&gt; &amp;gt; &lt;strong&gt;Users &amp;amp; Permissions plugin&lt;/strong&gt; &amp;gt; &lt;strong&gt;Roles&lt;/strong&gt; &amp;gt; &lt;strong&gt;Public&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9kebwo8ahxt0es5mqlai.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9kebwo8ahxt0es5mqlai.png" alt="Image description" width="466" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Grant access to the &lt;code&gt;android&lt;/code&gt; and &lt;code&gt;ios&lt;/code&gt; collections:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fysjvqzymn5dd5p6kvv5a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fysjvqzymn5dd5p6kvv5a.png" alt="Image description" width="800" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click &lt;strong&gt;Save&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Step 3: Add Content to Collections
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;In the sidebar, select &lt;strong&gt;Content Manager&lt;/strong&gt; and choose &lt;code&gt;android&lt;/code&gt; or &lt;code&gt;ios&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Create a new entry and fill in the required fields, including version and bundle file:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzbbrfrwxy7zkcny3jx48.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzbbrfrwxy7zkcny3jx48.png" alt="Image description" width="800" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Mark the entry as &lt;strong&gt;Published&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjwlmjlzfsc4c9h1kjusw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjwlmjlzfsc4c9h1kjusw.png" alt="Image description" width="598" height="318"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Step 4: Get Public API Endpoints
&lt;/h1&gt;

&lt;p&gt;Now that the collections are ready, use the following API endpoints to retrieve bundles and versions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Android&lt;/strong&gt;: &lt;a href="http://localhost:1337/api/androids?populate=*&amp;amp;filters[targetVersion][$eq]=1.0.0&amp;amp;sort=id:desc" rel="noopener noreferrer"&gt;&lt;code&gt;http://localhost:1337/api/androids?populate=*&amp;amp;filters[targetVersion][$eq]=1.0.0&amp;amp;sort=id:desc&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;iOS&lt;/strong&gt;: &lt;a href="http://localhost:1337/api/ios?populate=*&amp;amp;filters[targetVersion][$eq]=1.0.0&amp;amp;sort=id:desc" rel="noopener noreferrer"&gt;&lt;code&gt;http://localhost:1337/api/ios?populate=*&amp;amp;filters[targetVersion][$eq]=1.0.0&amp;amp;sort=id:desc&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To find the endpoint's &lt;strong&gt;API ID (Plural)&lt;/strong&gt;, refer to this section:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F13zuqjblshcwrhak9q9n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F13zuqjblshcwrhak9q9n.png" alt="Image description" width="800" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The API response structure in TypeScript will look like this:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{&lt;br&gt;
    data: {&lt;br&gt;
        id: number;&lt;br&gt;
        documentId: string;&lt;br&gt;
        note: string;&lt;br&gt;
        targetVersion: string;&lt;br&gt;
        enable: boolean;&lt;br&gt;
        required: boolean;&lt;br&gt;
        createdAt: string;&lt;br&gt;
        updatedAt: string;&lt;br&gt;
        publishedAt: string;&lt;br&gt;
        silentMY: boolean;&lt;br&gt;
        silentSG: boolean;&lt;br&gt;
        bundle: {&lt;br&gt;
            id: number;&lt;br&gt;
            documentId: string;&lt;br&gt;
            name: string;&lt;br&gt;
            url: string;&lt;br&gt;
            size: number;&lt;br&gt;
            hash: string;&lt;br&gt;
            mime: string;&lt;br&gt;
            createdAt: string;&lt;br&gt;
            updatedAt: string;&lt;br&gt;
            publishedAt: string;&lt;br&gt;
        };&lt;br&gt;
    }[];&lt;br&gt;
}&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Step 5: Add Logic for Version Check and Update in React Native&lt;br&gt;
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a hook called &lt;code&gt;useUpdateVersion&lt;/code&gt; to check for updates:&lt;/p&gt;

&lt;p&gt;import React from "react";&lt;/p&gt;

&lt;p&gt;// Custom hook to handle OTA updates&lt;br&gt;
export const useUpdateVersion = () =&amp;gt; {&lt;br&gt;
const checkUpdate = async () =&amp;gt; {&lt;br&gt;
  // Placeholder for update checking logic&lt;br&gt;
};&lt;/p&gt;

&lt;p&gt;React.useEffect(() =&amp;gt; {&lt;br&gt;
  if (!&lt;strong&gt;DEV&lt;/strong&gt;) {&lt;br&gt;
    // Automatically check for updates in production mode&lt;br&gt;
    checkUpdate();&lt;br&gt;
  }&lt;br&gt;
}, []);&lt;br&gt;
};&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Define the API endpoint logic in &lt;code&gt;api.ts&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;import axios from "axios";&lt;br&gt;
import DeviceInfo from "react-native-device-info";&lt;br&gt;
import { Platform } from "react-native";&lt;/p&gt;

&lt;p&gt;// Function to request the latest OTA bundle from the CMS&lt;br&gt;
export async function requestUpdateBundle() {&lt;br&gt;
   const endpoint = Platform.OS === 'ios' ? "ios" : "androids";&lt;br&gt;
   const version = DeviceInfo.getVersion(); // Get the current app version&lt;br&gt;
   const response = await axios.get(&lt;br&gt;
       &lt;code&gt;http://localhost:1337/api/${endpoint}?populate=*&amp;amp;filters[targetVersion][$eq]=${version}&amp;amp;sort=id:desc&lt;/code&gt;&lt;br&gt;
   );&lt;br&gt;
   return response.data;&lt;br&gt;
}&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement the update logic in the &lt;code&gt;checkUpdate&lt;/code&gt; function:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;import React from "react";&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;import HotUpdate from "react-native-ota-hot-update";&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;import { requestUpdateBundle } from "./api";&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;import { Alert } from "react-native";&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;import ReactNativeBlobUtil from "react-native-blob-util";&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;// Custom hook to check for and apply OTA updates&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;export const useUpdateVersion = () =&amp;gt; {&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;// Function to start downloading and applying the update bundle&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const startUpdateBundle = (url: string, version: number) =&amp;gt; {&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;HotUpdate.downloadBundleUri(ReactNativeBlobUtil, url, version, {&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;updateSuccess: () =&amp;gt; {&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;// Restart the app to apply the update immediately&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;HotUpdate.resetApp();&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;},&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;updateFail: () =&amp;gt; {&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;// Log or show a message for update failure&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;},&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;restartAfterInstall: true, // Automatically restart the app after installing the update&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;progress: (received, total) =&amp;gt; {&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;// Update UI to show download progress&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;},&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;});&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;};&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;// Function to check for updates by querying the CMS&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const checkUpdate = async () =&amp;gt; {&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const bundle = await requestUpdateBundle();&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const currentVersion = await HotUpdate.getCurrentVersion();&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;if (bundle?.data?.length) {&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;// Filter the latest enabled bundle from the response&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const [itemVersion] = bundle.data.filter(item =&amp;gt; item.enable);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const latestVersion = itemVersion?.id || 0; // Use the bundle ID as the version number&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;if (latestVersion &amp;gt; currentVersion) {&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;// Prompt the user to update the app&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Alert.alert(&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;"New version available!",&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;"A new version has been released. Please update.",&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;[&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{ text: "Cancel", style: "cancel" },&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;text: "Update",&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;onPress: () =&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;startUpdateBundle(&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;itemVersion?.attributes?.bundle?.data?.attributes?.url,&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;latestVersion&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;),&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;},&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;};&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;React.useEffect(() =&amp;gt; {&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;if (!__DEV__) {&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;// Automatically check for updates when the app starts in production mode&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;checkUpdate();&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;}, []);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;};&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;You now have a fully functional CMS for managing React Native OTA updates, complete with admin panel capabilities. Strapi's API also allows integration with CI/CD pipelines for automated content and media uploads, you can refer Strapi's document. Happy coding!&lt;/p&gt;

&lt;p&gt;Source: &lt;a href="https://github.com/vantuan88291/react-native-ota-hot-update/blob/main/OTA_CMS.md" rel="noopener noreferrer"&gt;https://github.com/vantuan88291/react-native-ota-hot-update/blob/main/OTA_CMS.md&lt;/a&gt;&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>hotupdate</category>
      <category>ota</category>
      <category>cms</category>
    </item>
  </channel>
</rss>
