<?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: Ionic</title>
    <description>The latest articles on DEV Community by Ionic (@ionic).</description>
    <link>https://dev.to/ionic</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%2Forganization%2Fprofile_image%2F845%2F288b82aa-412f-40c5-ab05-0e408eff57d2.png</url>
      <title>DEV Community: Ionic</title>
      <link>https://dev.to/ionic</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ionic"/>
    <language>en</language>
    <item>
      <title>Introducing the New Overlay Hooks for Ionic React</title>
      <dc:creator>Ely Lucas</dc:creator>
      <pubDate>Mon, 09 Aug 2021 21:48:10 +0000</pubDate>
      <link>https://dev.to/ionic/introducing-the-new-overlay-hooks-for-ionic-react-190i</link>
      <guid>https://dev.to/ionic/introducing-the-new-overlay-hooks-for-ionic-react-190i</guid>
      <description>&lt;p&gt;Hello Friends! We know everyone is excited about the new features in Ionic Framework 6.0 beta, but that doesn't mean we're done with V5! In Ionic React 5.6, we packaged up a new set of hooks for controlling our overlay components that we think you might like. What is an overlay you ask? It’s the term we give components that display over your current content, such as alerts, modals, toasts, etc. &lt;/p&gt;

&lt;p&gt;In this post, I’m going to go over how to use the new hooks to display these components in your apps. But first, let's do a quick recap on how overlays worked before, and some of the challenges that you might encounter with them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overlay Components
&lt;/h2&gt;

&lt;p&gt;Each of the overlays has a React component that is exported from &lt;code&gt;@ionic/react&lt;/code&gt;, such as &lt;code&gt;IonAlert&lt;/code&gt; and &lt;code&gt;IonLoading&lt;/code&gt;.  These components take a prop called &lt;code&gt;isOpen&lt;/code&gt;, which determines if the overlay should be displayed or not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IonAlert&lt;/span&gt;
  &lt;span class="nx"&gt;isOpen&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;showAlert&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These components are great and they aren’t going away. The new hooks don't deprecate them in any way. However, there's some ceremony you have to observe to use them. &lt;/p&gt;

&lt;p&gt;First, managing the state that handles the &lt;code&gt;isOpen&lt;/code&gt; prop could be a challenge. If the state was contained in the component that the overlay was in, then it was no problem (like a local state variable from &lt;code&gt;useState&lt;/code&gt;). However, if the action to display the overlays was in a different part of the app, then you needed to use some state management technique or library to pass the &lt;code&gt;isOpen&lt;/code&gt; prop along.&lt;/p&gt;

&lt;p&gt;Second, each of the Overlay components required you to provide an &lt;code&gt;onDidDismiss&lt;/code&gt; callback that would flip the &lt;code&gt;isOpen&lt;/code&gt; prop back to false in case the overlay dismissed itself somehow. Not overriding it would cause &lt;code&gt;isOpen&lt;/code&gt; to stay true, and if your app tried to show the overlay again, then you would be setting true to true, and Ionic wouldn’t detect the change and, thus, wouldn't display it again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IonAlert&lt;/span&gt;
  &lt;span class="nx"&gt;isOpen&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;showAlert&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello there friend&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="nx"&gt;onDidDismiss&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setShowAlert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A third challenge was that it was difficult to display an overlay from outside of your component; for instance, if you wanted to display an alert when an API request failed. Ionic Angular had controller instances you could import to use in services to display overlays. In React, this was more difficult to do.&lt;/p&gt;

&lt;p&gt;The new overlay hooks in Ionic React 5.6 help with all these scenarios.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overlay Hooks
&lt;/h2&gt;

&lt;p&gt;The goal of the overlay hooks was to reduce this process and to make the usage of the overlays feel more natural for those writing functional React components.&lt;/p&gt;

&lt;p&gt;To get started with the hooks, you import the hook for the overlay you want to use from &lt;code&gt;@ionic/react&lt;/code&gt; like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useIonAlert&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@ionic/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, in your functional component, you call the hook to get back the show and hide methods, which get returned in an array similar to how &lt;code&gt;useState&lt;/code&gt; returns its members. We choose the array method of destructuring so naming the methods is easier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;showAlert&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hideAlert&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useIonAlert&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Most overlays dismiss themselves when the user is done interacting with them, so you won’t need the hide method for most scenarios.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then to display the overlay, you call the show method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;showAlert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://blog.ionicframework.com/wp-content/uploads/2021/07/alert-overlay.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m01dmt6I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.ionicframework.com/wp-content/uploads/2021/07/alert-overlay.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The alert will dismiss itself after the user clicks the "Ok" button. You don’t need to worry about doing any additional work when the overlays go away.&lt;/p&gt;

&lt;p&gt;Most of the overlay hooks have options that you can pass to them. The more common options can be passed in as additional parameters. For instance, the toast overlay's show method also takes the time to display the toast as its second parameter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;showToast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello from a toast!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will display the toast for three seconds, and then the toast will dismiss itself.&lt;/p&gt;

&lt;p&gt;More options can be sent by passing in an object instead of the separate parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;showToast&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;buttons&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hide&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;hideToast&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
  &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello, click hide to dismiss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;onDidDismiss&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dismissed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;              
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;React hooks can be used in other hooks as well. Because of this, it's possible to display an overlay from within other hooks, such as one responsible for fetching some data. Here is a sample custom hook to fetch a customer that displays a toast when the request fails:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useCustomer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCustomer&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Customer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;showToast&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useIonToast&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;fetchCustomer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;fetchCustomer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`myapi.com/customers/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;setCustomer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;showToast&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Oops, unable to get customer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;warning&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;buttons&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;close&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;showToast&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  More Info
&lt;/h2&gt;

&lt;p&gt;To learn more about the new hooks, visit our &lt;a href="https://ionicframework.com/docs/react/overlays"&gt;guide on using overlays in Ionic React&lt;/a&gt;, and check out the docs for each of the overlay components for usage examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ionicframework.com/docs/api/action-sheet"&gt;Action Sheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ionicframework.com/docs/api/modal#usage"&gt;Alert&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ionicframework.com/docs/api/loading"&gt;Loading&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ionicframework.com/docs/api/modal"&gt;Modal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ionicframework.com/docs/api/picker"&gt;Picker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ionicframework.com/docs/api/popover"&gt;Popover&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ionicframework.com/docs/api/toast"&gt;Toast&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let us know in the comments down below if you have any feedback, and until next time, happy coding!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>10 Reasons to Choose Ionic for Mobile Development</title>
      <dc:creator>Max Lynch</dc:creator>
      <pubDate>Thu, 22 Jul 2021 18:47:57 +0000</pubDate>
      <link>https://dev.to/ionic/10-reasons-to-choose-ionic-for-mobile-development-213a</link>
      <guid>https://dev.to/ionic/10-reasons-to-choose-ionic-for-mobile-development-213a</guid>
      <description>&lt;p&gt;The &lt;a href="https://ionicframework.com/"&gt;Ionic&lt;/a&gt; stack makes it easy to build iOS, Android, Desktop, and Progressive Web Apps using standard web technology. There are a lot of options for cross-platform mobile and web app development, so when should you or your team consider using Ionic?&lt;/p&gt;

&lt;p&gt;Here are 10 reasons you might want to choose Ionic:&lt;/p&gt;

&lt;h2&gt;
  
  
  1. You’re a web developer
&lt;/h2&gt;

&lt;p&gt;One of the best reasons to choose Ionic is if you’re a web developer and want to stay in the web development world. The Ionic stack is built on standard web development technologies meaning you can build the majority of your app directly in a browser and use standard browser development tools and technologies, while still deploying and building a traditional native app.&lt;/p&gt;

&lt;p&gt;Other cross-platform toolkits don’t use the web development stack so aren’t the best fit for web developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. You are building a new app dev engineering team
&lt;/h2&gt;

&lt;p&gt;Because the Ionic stack is focused on web developers, it’s the easiest cross-platform technology to hire for because there are considerably more web developers in the world than any other mobile technology. Any web developer can easily learn to build apps using the Ionic stack and it will be the most familiar to them, and have the best compatibility with popular web frameworks like React, Angular, and Vue.&lt;/p&gt;

&lt;p&gt;And hiring web developers means they can then develop for mobile, desktop, and web without the need to hire specialist teams for each platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. You’re an enterprise (or work at one)
&lt;/h2&gt;

&lt;p&gt;Ionic is the only cross-platform development stack that has &lt;a href="https://ionic.io/"&gt;Enterprise support and integrations&lt;/a&gt; for teams building employee and customer-facing apps. Ionic offers dedicated support, security features like &lt;a href="https://ionic.io/products/identity-vault"&gt;Biometrics&lt;/a&gt; and &lt;a href="https://ionic.io/products/auth-connect"&gt;Single Sign-on&lt;/a&gt;, and cloud services for &lt;a href="https://ionic.io/appflow"&gt;remote app updates, app builds, and app store distribution&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ionic is the industry leader in enterprise app development with hundreds of Fortune 1000 customers, and &lt;a href="https://www.g2.com/products/ionic/reviews"&gt;customers love it&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. You have existing web experiences and investments
&lt;/h2&gt;

&lt;p&gt;Because the Ionic stack is based around standard web development, it’s the only cross-platform solution that supports bringing existing web experiences, libraries, and other web code into an app.&lt;/p&gt;

&lt;p&gt;This is particularly important for enterprises or teams with a heavy web presence that want to bring those experiences into existing apps, such as traditional native apps.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. You want to join a massive community of developers
&lt;/h2&gt;

&lt;p&gt;Building apps with popular technologies makes it easier to hire for, easier to find partners, and easier to find resources on the web as you build your app.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://ionicframework.com/community"&gt;Ionic developer community&lt;/a&gt; is massive, with millions of developers around the world having built apps on the stack. Passionate community members build and share tutorials, add-ons, templates, and more, and developers can find help on the &lt;a href="https://forum.ionicframework.com/"&gt;Ionic forum&lt;/a&gt; and Stack Overflow.&lt;/p&gt;

&lt;p&gt;But Ionic is unique in that the community isn’t just limited to Ionic’s bubble. Because Ionic is based on standard web technologies, the addressable community goes beyond Ionic and overlaps with the broader web development community, such as the React, Angular, and Vue communities. This is critical when considering building out app dev teams because an Ionic team can be built with web developers, but other technologies require hiring specialists on languages and technologies that are not widely used.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. You’re on a tight deadline
&lt;/h2&gt;

&lt;p&gt;We often hear from teams who spent months building their app using a different technology, failed to hit deadlines, and then switched to Ionic and had the new app working and surpassing the old one within weeks.&lt;/p&gt;

&lt;p&gt;Ionic is highly productive because the web is highly productive. And one app can run on multiple platforms so development time can be upwards of 3-4x faster than traditional native development!&lt;/p&gt;

&lt;h2&gt;
  
  
  7. You want your apps to be on iOS, Android, Web, and even desktop on day one
&lt;/h2&gt;

&lt;p&gt;Ionic apps run anywhere the web runs, and with the same code! And Ionic has official support for iOS, Android, Desktop, and Web, so teams can hit the ground running — targeting all these platforms and their respective user bases at launch.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. You want to be able to benefit from both app store &lt;em&gt;and&lt;/em&gt; web traffic
&lt;/h2&gt;

&lt;p&gt;Because the Ionic stack is based on web technology, teams can target the web and build a high-performance Progressive Web App (PWA).&lt;/p&gt;

&lt;p&gt;This means teams can reach users both in traditional app stores but also on the web and through Google search to maximize reach and have the best chance for a successful app project. We’ve &lt;a href="https://dev.to/ionic/app-store-or-web-why-not-both-3fa2"&gt;talked at length&lt;/a&gt; about how the Ionic stack gives you the best distribution optionality of any cross-platform technology in the market.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. You already have web developers on your team
&lt;/h2&gt;

&lt;p&gt;If you already have web developers on your team or at your company, using the Ionic stack is a no-brainer! Web developers can easily become mobile developers by learning to use the Ionic stack, including Ionic’s &lt;a href="https://ionicframework.com/docs/components"&gt;100+ mobile-optimized UI components&lt;/a&gt; and &lt;a href="https://capacitorjs.com/"&gt;the native runtime&lt;/a&gt; that provides hooks into functionality on each platform. Ionic also supplies the means to build and deploy those apps.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. You’re a student or new to app development
&lt;/h2&gt;

&lt;p&gt;Ionic is the most accessible platform for cross-platform app development. If you’re familiar with basic web development you can build real mobile apps (and desktop + web apps) today! &lt;/p&gt;

&lt;p&gt;Learning Ionic requires learning a few new HTML tags, some new JavaScript APIs for native functionality, and then just building your app using your framework of choice (React/Angular/Vue/etc).&lt;/p&gt;

&lt;p&gt;And the best thing is you continue to build your web development skills at the same time and don't have to change your technical career focus.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get started today
&lt;/h2&gt;

&lt;p&gt;There you have it, ten good reasons you and your team might want to adopt Ionic.&lt;/p&gt;

&lt;p&gt;If you're interested in building cross-platform apps using Ionic and modern web technologies, &lt;a href="https://ionicframework.com/"&gt;Get started&lt;/a&gt; with Ionic today.&lt;/p&gt;

</description>
      <category>ionic</category>
      <category>mobile</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>App store or web? Why not both!?</title>
      <dc:creator>Max Lynch</dc:creator>
      <pubDate>Wed, 09 Jun 2021 16:12:23 +0000</pubDate>
      <link>https://dev.to/ionic/app-store-or-web-why-not-both-3fa2</link>
      <guid>https://dev.to/ionic/app-store-or-web-why-not-both-3fa2</guid>
      <description>&lt;p&gt;Most app development technologies force teams  to make hard decisions about where they will distribute their apps, usually either app stores as a native app or the web as a Progressive Web App.&lt;/p&gt;

&lt;p&gt;Building a native Swift (iOS) or Kotlin (Android) app, for example, obviously limits teams to just those respective platforms. But others have more subtle restrictions. Xamarin enables you to build for iOS, Android, and Desktop, but not for the web, meaning no access to a major chunk of mobile traffic and app-consuming users. React Native’s View elements can be abstracted to have the same API on the web but you will need to write completely separate view code for it, avoid using certain standard web features, and use different calls for certain APIs, so it’s an additional investment. Flutter can be used to build iOS, Android, and Web apps, but its web support requires multiple MBs of code for users so it’s not appropriate for high-performance Progressive Web Apps and speed-sensitive web sites like those that depend on search engine rankings and SEO.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://capacitorjs.com/"&gt;Capacitor&lt;/a&gt;, a universal app runtime, avoids these tradeoffs by targeting one universal runtime (the web), and giving you maximum optionality for where you distribute the app that you build. You can deploy your app with one codebase anywhere your users are, even if that happens to change! That might mean the app stores today, but it could mean the web and desktop tomorrow.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Optionality Looks Like
&lt;/h2&gt;

&lt;p&gt;I was recently helping a team think through an app project they were going to deploy to the app stores on iOS and Android. They were using Capacitor with React, using a home-grown UI based on Tailwind. &lt;/p&gt;

&lt;p&gt;During development, the team decided that they wanted to have a strong web portion to their app in order to easily acquire users, benefit from instant access and SEO on the web, and avoid app install bounce risk (meaning, the user leaves without ever installing the app, which is very common in the mobile world!)&lt;/p&gt;

&lt;p&gt;Since their app was built with &lt;a href="https://capacitorjs.com/"&gt;Capacitor&lt;/a&gt;, utilizing Capacitor’s &lt;a href="https://capacitorjs.com/docs/plugins"&gt;cross-platform APIs&lt;/a&gt;, they could simply deploy the same app with the same code as a Progressive Web App hosted on a platform like Vercel or Netlify.&lt;/p&gt;

&lt;p&gt;And this decision didn’t preclude them from also shipping a native iOS and Android app. They decided that they would unlock some additional features that depended on native functionality missing from the browser environment for users that were “activated” and likely to stick around.&lt;/p&gt;

&lt;p&gt;Doing so in Capacitor was straightforward because Capacitor APIs are identical on iOS, Android, and the Web, and Capacitor comes with a &lt;a href="https://capacitorjs.com/docs/core-apis/web#isnativeplatform"&gt;number of utilities&lt;/a&gt; for adding conditional platform-specific code if desired.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this Matters
&lt;/h2&gt;

&lt;p&gt;For new projects, the greatest risk isn’t technical but rather that no one uses your app and it never gains meaningful traction or scale. One of the best ways to avoid that is to reach the broadest possible segment of your target audience on day one.&lt;/p&gt;

&lt;p&gt;For most companies, their audience isn’t on a single platform, form factor, or environment (such as mobile or web). This is especially true for consumer and enterprise consumer companies. In fact, there’s a good chance a majority of users aren’t even on a platform that you, the developer, actually use primarily (such as Android if you’re an iPhone user or web apps if you’re in the US and used to installed native apps).&lt;/p&gt;

&lt;p&gt;Having optionality might mean the difference between your app project failing or succeeding, and nothing could matter more than that.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does this compare to Progressive Web Apps?
&lt;/h2&gt;

&lt;p&gt;One of the things to think about when building a Progressive Web App &lt;em&gt;not&lt;/em&gt; with Capacitor, is that it will constrain your app to running only in a traditional browser context. This means it will only be accessible on the web and not have the option to access native APIs that don't have a browser analog since it cannot be distributed in popular mobile app stores.&lt;/p&gt;

&lt;p&gt;Thus, the decision to build a Progressive Web App can also be limiting. But in this case a very straightforward way to add native iOS and Android support is by installing Capacitor into your Progressive Web App. &lt;/p&gt;

&lt;p&gt;Capacitor has &lt;a href="https://capacitorjs.com/docs/web"&gt;full Progressive Web App support&lt;/a&gt; and apps use the same Capacitor API calls regardless of the platform they are running on. This makes it easy to bring it to iOS and Android with the same code.&lt;/p&gt;

&lt;p&gt;In that sense, Capacitor is "web app virtualization layer" that enables standard web apps to run anywhere with the same APIs, regardless of the "host" platform underneath.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who's using Capacitor today?
&lt;/h2&gt;

&lt;p&gt;Capacitor is growing quickly (100% YoY) and is installed &lt;a href="https://npmcharts.com/compare/@capacitor/core"&gt;over 500k times per month&lt;/a&gt;. Teams at companies like Burger King, Tim Hortons, Workgrid (Liberty Mutual), and Fidelity, to name a few, are all using Capacitor to enable their web teams to deploy iOS, Android, and Web apps with the same code.&lt;/p&gt;

&lt;p&gt;Capacitor was also rated &lt;a href="https://2020.stateofjs.com/en-US/technologies/mobile-desktop/"&gt;#1 in satisfaction among mobile development tools&lt;/a&gt; on the latest State of JS survey.&lt;/p&gt;

&lt;p&gt;Capacitor was created by the team behind the popular &lt;a href="https://ionicframework.com/"&gt;Ionic Framework&lt;/a&gt; as a  replacement for Cordova for deploying modern &lt;a href="https://webnative.tech"&gt;Web Native&lt;/a&gt; apps on iOS, Android, Desktop, and Web.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get started
&lt;/h2&gt;

&lt;p&gt;Getting started with Capacitor and building full distribution optionality into your mobile-enabled web app is as easy as installing the Capacitor library and running a few commands.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://capacitorjs.com/docs"&gt;Get started&lt;/a&gt; with Capacitor today and &lt;a href="https://twitter.com/capacitorjs"&gt;follow us&lt;/a&gt; for more resources and updates on the project!&lt;/p&gt;

</description>
      <category>ionic</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Building a better Web View for mobile apps</title>
      <dc:creator>Max Lynch</dc:creator>
      <pubDate>Tue, 18 May 2021 15:02:21 +0000</pubDate>
      <link>https://dev.to/ionic/building-a-better-web-view-for-mobile-apps-183</link>
      <guid>https://dev.to/ionic/building-a-better-web-view-for-mobile-apps-183</guid>
      <description>&lt;p&gt;Web Views are among the most widely used components in mobile apps for good reason: most apps need to incorporate some internal or external web experience at some point.&lt;/p&gt;

&lt;p&gt;Because of this, Apple and Google provide basic Web View controls out of the box:  iOS with &lt;code&gt;WKWebView&lt;/code&gt;, and Android with &lt;code&gt;WebView&lt;/code&gt; (there are other options on Android but this is the primary one most apps use).&lt;/p&gt;

&lt;p&gt;Unfortunately, using these Web Views is anything but simple, and native developers are stuck reinventing the wheel every time they need to use one of these Web Views in their app. Luckily, that pain is coming to an end. Read on to learn about &lt;a href="https://ionic.io/portals"&gt;our take&lt;/a&gt; on a better drop-in Web View for iOS and Android native app developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Use case for Web Views
&lt;/h2&gt;

&lt;p&gt;Web Views feature prominently in many apps. Some apps are built entirely around a single primary Web View instance, and other traditional native apps selectively display and embed Web Views to bring in web experiences.&lt;/p&gt;

&lt;p&gt;For apps where most of the functionality and content is built in the Web View, the use case for Web Views is obvious. I don’t want to spend more time talking about that use case here but tools like &lt;a href="https://capacitorjs.com/"&gt;Capacitor&lt;/a&gt; and &lt;a href="https://ionicframework.com/"&gt;Ionic Framework&lt;/a&gt; excel at this and are widely used.&lt;/p&gt;

&lt;p&gt;For traditional native apps, the use cases for embedding web experiences might vary from from embedding an existing web experience such as a mortgage application or a survey, to displaying web-based authentication forms, to hosting prototype web experiences before porting to native.&lt;/p&gt;

&lt;p&gt;Generally, the more established the company, the larger their web development teams, and the more prominent that company is on the web, the more likely they will need to bring in web experiences into their mobile app at some point in time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem with Web Views Today
&lt;/h2&gt;

&lt;p&gt;Generally, Web Views provided by Apple and Google are spartan and bare bones. Nearly every native developer that we’ve talked to has expressed annoyance at extending the stock Web View controls and then maintaining a fairly complex set of code to host web experiences in the app. Thus, the problem with the stock Web Views is that they just don't do enough and don't cover the surface area of what native developers typically need them to do.&lt;/p&gt;

&lt;p&gt;I have first-hand experience with this as the creator of &lt;a href="https://capacitorjs.com/"&gt;Capacitor&lt;/a&gt;, which is essentially a supercharged Web View for hosting web apps that need to interface with existing native code. Capacitor is many tens of thousands of lines of code that wrap the core Web Views available on each platform and add a number of features, like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An API for adding new native “plugins” that expose new Web APIs to web developers based on custom native code, and do so in a controlled fashion and with a web-developer approved API (promises, typescript, etc)&lt;/li&gt;
&lt;li&gt;A high performance bridge for communicating between web and native and keeping track of invocations and returning results back to the caller&lt;/li&gt;
&lt;li&gt;Handling references to assets to host web content offline and correctly stream data for Web HTML controls like video and audio (surprisingly tricky).&lt;/li&gt;
&lt;li&gt;Marshalling data between the native and web layer&lt;/li&gt;
&lt;li&gt;Managing native elements such as alert dialogs, keyboard, status bar, scroll regions...all while correctly handling orientation changes&lt;/li&gt;
&lt;li&gt;Handling delegate methods for navigation, load, errors, permission requests, and other general housekeeping.&lt;/li&gt;
&lt;li&gt;Updating embedded web experiences dynamically and out of band with the slower native release cycle&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And then doing this on both iOS and Android (on which even more code and complexity is required). And this list is not nearly exhaustive!&lt;/p&gt;

&lt;p&gt;It seems like every meaningfully large native app ends up implementing a subset of the features above, which is no small task!&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a better Web View
&lt;/h2&gt;

&lt;p&gt;It took many months to build the first version of Capacitor due to the complexity required in building a robust Web View wrapper with the above features, and I never want another developer to have to go through that again.&lt;/p&gt;

&lt;p&gt;Sadly, almost every native app developer does have to go through this today, and then has a bunch of complex, custom code to maintain. All that when they could have just imported a stable, well maintained, feature-rich Web View control and got back to the fun part of building their app.&lt;/p&gt;

&lt;p&gt;When we realized that what we had with Capacitor could be pulled out to help native app developers everywhere, we knew we were on to something: a much better Web View for native apps. &lt;/p&gt;

&lt;h2&gt;
  
  
  Announcing Ionic Portals
&lt;/h2&gt;

&lt;p&gt;We’ve been working on bringing the Web View technology behind Capacitor to native apps and native developers everywhere, and we are taking the wraps off the first iteration of that product today: &lt;a href="https://ionic.io/portals"&gt;Ionic Portals&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ionic Portals is a drop-in Web View component for native apps that handles all the messy, annoying parts of using a Web View in a native app. Developers can host multiple different web experiences through different “portals”, and isolate them, selectively exposing custom native functionality that each one needs. Teams can remotely update and deploy new web experiences dynamically to deploy new features and tests in realtime and without disrupting the native app release process.&lt;/p&gt;

&lt;p&gt;Ionic Portals uses the same technology currently deployed in major consumer apps like Burger King, Paylocity, H&amp;amp;R Block,  Aflac and more, but distributed as a drop-in control for existing native apps.&lt;/p&gt;

&lt;p&gt;And on top of all this, Ionic Portals is maintained and supported by us, so you have one less component to have to maintain in your app.&lt;/p&gt;

&lt;p&gt;We’re currently working with a few teams who are desperate for a better Web View control in their native apps. If you’re interested in trying it out and sharing your feedback as we built out the product, we’d love for you to get in touch. Visit the &lt;a href="https://ionic.io/portals"&gt;Ionic Portals page&lt;/a&gt; to see a demo and learn more about our take on a dramatically improved Web View for native apps.&lt;/p&gt;

</description>
      <category>android</category>
      <category>ios</category>
      <category>swift</category>
      <category>reactnative</category>
    </item>
    <item>
      <title>Build Mobile Apps with Tailwind CSS, Next.js, Ionic Framework, and Capacitor</title>
      <dc:creator>Max Lynch</dc:creator>
      <pubDate>Mon, 01 Feb 2021 15:24:54 +0000</pubDate>
      <link>https://dev.to/ionic/build-mobile-apps-with-tailwind-css-next-js-ionic-framework-and-capacitor-3kij</link>
      <guid>https://dev.to/ionic/build-mobile-apps-with-tailwind-css-next-js-ionic-framework-and-capacitor-3kij</guid>
      <description>&lt;p&gt;A very popular stack for building responsive web apps is &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind CSS&lt;/a&gt; and &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt; by &lt;a href="https://vercel.com/" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Tailwind, a utility-first CSS framework that replaces the need to write custom class names or even any CSS at all in many cases, makes it easy to design responsive web apps through small CSS building blocks and a flexible design foundation.&lt;/p&gt;

&lt;p&gt;Next.js, a React framework for building high performance React apps, is one of the leading environments for building production React apps on the web.&lt;/p&gt;

&lt;p&gt;As these technologies have grown, they are increasingly used together for web app development (in fact, Next.js is working on an &lt;a href="https://github.com/vercel/next.js/discussions/20030" rel="noopener noreferrer"&gt;RFC for official Tailwind integration&lt;/a&gt;). This has prompted many users of these projects to ask whether they can be used to build mobile apps, too.&lt;/p&gt;

&lt;p&gt;Turns out, they can! And they make a great fit for cross-platform mobile development when paired with &lt;a href="https://ionicframework.com/" rel="noopener noreferrer"&gt;Ionic Framework&lt;/a&gt; and &lt;a href="https://capacitorjs.com/" rel="noopener noreferrer"&gt;Capacitor&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As I started playing with these technologies, I realized that each had a natural fit in a combined mobile stack, and I wanted to put together a solid starting foundation for others interested in building real iOS and Android apps using these technologies.&lt;/p&gt;

&lt;p&gt;If you're confused by all the project names and how they work together, don't worry, I'll break down each part of the stack each project is concerned with, along with some visuals and code samples demonstrating how all the projects work together. At the end I'll share &lt;a href="https://github.com/mlynch/nextjs-tailwind-ionic-capacitor-starter" rel="noopener noreferrer"&gt;a starter project&lt;/a&gt; with these technologies installed and working together that can form the foundation of your next app.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stack Visualized
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fbwhawidkv6ju58h8rdqw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fbwhawidkv6ju58h8rdqw.png" alt="Diagram of layers in a Capacitor Tailwind Next.js Ionic app"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above is a live screenshot of a React app built with Next.js that is using Ionic Framework and Tailwind for the UI experience, and Capacitor to natively deploy that app to iOS and provide access to any Native APIs the app uses.&lt;/p&gt;

&lt;p&gt;There are a lot of projects working in tandem to provide the full experience here. To visualize it, I've tried to overlay the different layers and how they correspond to each project in this diagram above.&lt;/p&gt;

&lt;p&gt;We can see that Capacitor is concerned with the entire app and device layer of the app, Next.js is concerned with the entire web/React app our code and UI is running in, then Ionic handles the "platform UI" including navigation toolbar (including system title and toolbar buttons) as well as the bottom tabs.&lt;/p&gt;

&lt;p&gt;Finally, Tailwind is used to then style and customize the content of each page, which is where the bulk of the app-specific styling will occur.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mobile UI and Native Runtime
&lt;/h2&gt;

&lt;p&gt;If your experience building with web technologies is primarily for desktop or responsive sites, you might not be familiar with mobile-focused libraries Ionic Framework and Capacitor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ionicframework.com/" rel="noopener noreferrer"&gt;Ionic Framework&lt;/a&gt; is a cross-platform, mobile-focused UI library for the web. It provides ~100 components that implement platform UI standards across iOS and Android. Things like toolbars, navigation/transitions, tabs, dialog windows, and more. The big draw is those components work on the web and work in frameworks like React, Angular, Vue, or plain HTML/CSS/JS.&lt;/p&gt;

&lt;p&gt;Ionic Framework is highly popular and powers upwards of 15% of apps in the app store.&lt;/p&gt;

&lt;p&gt;Historically, Ionic Framework would be paired with a project like Cordova which provided the native iOS and Android building and runtime capabilities. However, most new Ionic Framework apps use Capacitor for this part of the stack.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://capacitorjs.com/" rel="noopener noreferrer"&gt;Capacitor&lt;/a&gt; is a project built by the team behind Ionic Framework focused on the &lt;em&gt;native&lt;/em&gt; side of a web-focused mobile app.&lt;/p&gt;

&lt;p&gt;Capacitor provides a plugin layer and runtime that runs web apps natively on iOS, Android, Desktop, and Web, and provides full access to device APIs and features (including extending the web environment by writing additional native Swift/Java code).&lt;/p&gt;

&lt;p&gt;As such, any popular web technologies and libraries can be used to build mobile apps with Capacitor, and then deploy the same apps with the same code to the web and desktop.&lt;/p&gt;

&lt;p&gt;And, to top it all off, Capacitor was just &lt;a href="https://2020.stateofjs.com/en-US/technologies/mobile-desktop/" rel="noopener noreferrer"&gt;rated the second highest in satisfaction&lt;/a&gt; among popular Mobile &amp;amp; Desktop Tools on the State of JS 2020 Survey! If your last experience with this mobile development approach was with Cordova, we think you'll find Capacitor to be a big improvement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing the Next.js + Tailwind CSS + Ionic Framework + Capacitor Starter
&lt;/h2&gt;

&lt;p&gt;Now that you have a sense for how these technologies all work together to make it easy for web developers to build mobile apps, let's take a look at a real demo and starter project (&lt;a href="https://github.com/mlynch/nextjs-tailwind-ionic-capacitor-starter" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt;):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Foxj2evycaakr0r8q5pvc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Foxj2evycaakr0r8q5pvc.png" alt="Next.js Tailwind Ionic Capacitor Starter"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's take a look at the main Feed page (seen above in the screenshot) for an example of how the different technologies in use work together:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;IonPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;IonHeader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;IonToolbar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;IonTitle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;IonButtons&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;IonButton&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;IonIcon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;IonContent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@ionic/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;notificationsOutline&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ionicons/icons&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Notifications&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Notifications&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Card&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../ui/Card&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getHomeItems&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../store/selectors&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Store&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;FeedCard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;authorAvatar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Card&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my-4 mx-auto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rounded-t-xl h-32 w-full object-cover&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;px-4 py-4 bg-white rounded-b-xl dark:bg-gray-900&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h4&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;font-bold py-0 text-s text-gray-400 dark:text-gray-500 uppercase&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h4&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;font-bold text-2xl text-gray-800 dark:text-gray-100&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sm:text-sm text-s text-gray-500 mr-1 my-3 dark:text-gray-400&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flex items-center space-x-4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;authorAvatar&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rounded-full w-10 h-10&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h3&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text-gray-500 dark:text-gray-200 m-l-8 text-sm font-medium&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h3&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Card&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Feed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;homeItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getHomeItems&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;showNotifications&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setShowNotifications&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IonPage&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IonHeader&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IonToolbar&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IonTitle&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Feed&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/IonTitle&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IonButtons&lt;/span&gt; &lt;span class="nx"&gt;slot&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;end&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IonButton&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setShowNotifications&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IonIcon&lt;/span&gt; &lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;notificationsOutline&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/IonButton&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/IonButtons&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/IonToolbar&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/IonHeader&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IonContent&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ion-padding&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;fullscreen&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IonHeader&lt;/span&gt; &lt;span class="nx"&gt;collapse&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;condense&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IonToolbar&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IonTitle&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;large&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Feed&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/IonTitle&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/IonToolbar&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/IonHeader&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Notifications&lt;/span&gt;
          &lt;span class="nx"&gt;open&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;showNotifications&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;onDidDismiss&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setShowNotifications&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
        &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;homeItems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FeedCard&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;))}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/IonContent&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/IonPage&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Feed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;As we can see, we use Ionic Framework controls (&lt;code&gt;IonPage&lt;/code&gt;, &lt;code&gt;IonHeader&lt;/code&gt;, &lt;code&gt;IonContent&lt;/code&gt;, &lt;code&gt;IonToolbar&lt;/code&gt;, etc) for the structure of the page (these controls implement iOS and Android platform-specific styles and navigation/transition behavior), then we use Tailwind for the page content that is where our custom design lives (which will tend to be in &lt;code&gt;IonContent&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;If we look at another page that is just a simple list, we see that we don't use Tailwind at all, because the user would expect this page to be a standard iOS/Android list and toggle button (&lt;a href="https://github.com/mlynch/nextjs-tailwind-ionic-capacitor-starter/blob/main/components/pages/Settings.jsx" rel="noopener noreferrer"&gt;code here&lt;/a&gt;):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdpxgbwh5x2tt6dfn5pu7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdpxgbwh5x2tt6dfn5pu7.png" alt="Settings Page Example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, we tend to use Tailwind more for pages with a lot of custom design and assets. That's by design. Generally when building a native mobile app, we want to use platform conventions as much as possible, especially for experience and performance-sensitive elements like Lists, Toolbars, Tabs, and Form inputs. However, for the &lt;code&gt;Feed&lt;/code&gt; page, which has a pretty custom UI experience, we end up getting a lot of mileage out of Tailwind.&lt;/p&gt;

&lt;p&gt;So, in general, the way to think about when to lean more on Ionic Framework and when to lean on Tailwind is when your UI experience will heavily use typical mobile UI elements (prefer Ionic components) or when it will be more custom (prefer Tailwind).&lt;/p&gt;

&lt;p&gt;Finally, this starter also comes with a few small opinions around folder structure and state management. For state management, the library &lt;a href="https://lostpebble.github.io/pullstate/" rel="noopener noreferrer"&gt;pullstate&lt;/a&gt; is used which is a simple yet powerful state management library with a hooks-based API (I wrote &lt;a href="https://dev.to/ionic/pullstate-simple-hooks-based-state-management-for-react-5bc4"&gt;more about it here&lt;/a&gt;). If want to use something else, removing it is easy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying to iOS and Android
&lt;/h2&gt;

&lt;p&gt;The app can be easily deployed to iOS and Android using Capacitor and its local CLI tools. After running &lt;code&gt;npm install&lt;/code&gt;, you'll have the &lt;code&gt;npx cap&lt;/code&gt; command available, which enables a &lt;a href="https://capacitorjs.com/docs/basics/workflow" rel="noopener noreferrer"&gt;native development workflow&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;To add an iOS or Android native project:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npx cap add ios
npx cap add android


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then, to build the Next.js app, export it, and copy it to the native projects:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npm run build
npm run &lt;span class="nb"&gt;export
&lt;/span&gt;npx cap copy


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This command is needed every time the built output changes. However, you can enable livereload during development (see the &lt;code&gt;README&lt;/code&gt; for more info).&lt;/p&gt;

&lt;p&gt;Then, you can launch Xcode and/or Android Studio to build and run the native project:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;p&gt;npx cap open ios&lt;br&gt;
npx cap open android&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Next steps&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;If you've been interested in building mobile apps using popular web dev projects like Next.js or Tailwind, hopefully this starter provides inspiration and a solid foundation for building your next app using web technologies. It's worth mentioning this exact same approach can be used with other UI libraries (like material, bootstrap, or your own!).&lt;/p&gt;

&lt;p&gt;When you're ready, dig into &lt;a href="https://github.com/mlynch/nextjs-tailwind-ionic-capacitor-starter" rel="noopener noreferrer"&gt;the starter project&lt;/a&gt;, follow the &lt;a href="https://capacitorjs.com/" rel="noopener noreferrer"&gt;Capacitor&lt;/a&gt; and &lt;a href="https://ionicframework.com/" rel="noopener noreferrer"&gt;Ionic Framework&lt;/a&gt; docs, and get building!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tailwindcss</category>
      <category>javascript</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>How to Reduce the Number of Renders in an Ionic React App</title>
      <dc:creator>Ely Lucas</dc:creator>
      <pubDate>Thu, 28 Jan 2021 15:45:05 +0000</pubDate>
      <link>https://dev.to/ionic/how-to-reduce-the-number-of-renders-in-an-ionic-react-app-26mm</link>
      <guid>https://dev.to/ionic/how-to-reduce-the-number-of-renders-in-an-ionic-react-app-26mm</guid>
      <description>&lt;p&gt;Hello friends!&lt;/p&gt;

&lt;p&gt;Welcome to this first article in a series that I plan on doing around quick tips for routing in Ionic React.&lt;/p&gt;

&lt;p&gt;To kick this series off, I'm going to answer one of the top questions I get, and that's "Why do my Ionic Pages render so much?"&lt;/p&gt;

&lt;p&gt;For starters, you shouldn't be overly concerned with multiple renders. During the render phase, React will build up a representation of your component in what is called the Virtual DOM. Building this VDOM is relatively cheap. Afterward, React will compare the VDOM to what is in the actual DOM, and it will only do the costly DOM updates if there are actual changes.&lt;/p&gt;

&lt;p&gt;This means that if your component renders again, but there aren’t any changes, then the cost is minimal.&lt;/p&gt;

&lt;p&gt;However, there are a couple of drawbacks to rendering too much. First, React must construct the VDOM and run its diffing algorithm for each render call. While this is highly optimized and fast, doing so is wasteful if the component doesn’t need to update. Second, if you have costly code in the render method, it will get run each time. &lt;/p&gt;

&lt;p&gt;Also, if you are like me, it can drive you bonkers.&lt;/p&gt;

&lt;p&gt;Therefore, trying to cut down on the number of renders is a micro-optimization, but sometimes it’s one worth taking.&lt;/p&gt;

&lt;p&gt;In this article, we will take a look at why render gets called multiple times, and then I'll show you some techniques you can use in your own apps to help reduce them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Setup
&lt;/h2&gt;

&lt;p&gt;If you want to follow along, start up a new Ionic React app using the &lt;a href="https://ionicframework.com/docs/intro/cli" rel="noopener noreferrer"&gt;Ionic CLI&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ionic start RenderTest tabs &lt;span class="nt"&gt;--type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;react 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in the Tab1.tsx file, add a log statement inside of the function so we can see each time the component is rendered:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Tab1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tab1 render&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;IonPage&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;IonPage&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fire up the app with &lt;code&gt;ionic serve&lt;/code&gt;, and you will see that, on initial load, the Tab1 page renders twice:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fi33gvnx1huo6vblmgm92.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fi33gvnx1huo6vblmgm92.png" alt="initial-render"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, if you click around on the tabs, you will see that Tab1 renders 3-4 times each time you switch a tab! What's going on here?&lt;/p&gt;

&lt;h2&gt;
  
  
  Why you render so much?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzldjszkxtfzc0yetpsr7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzldjszkxtfzc0yetpsr7.jpg" alt="yodawgrender"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every page in an Ionic React app is wrapped with an &lt;code&gt;IonPage&lt;/code&gt; component. The IonPage not only provides some div containers for holding your page and styles around it, but it is also very important when it comes to doing page transitions. &lt;/p&gt;

&lt;p&gt;There is some semi-complicated logic that goes on in the background in regards to getting a reference to these IonPages when they are transitioned to and from. Unfortunately, to get the reference, we have to wait until the component mounts, then grab the reference, and store that reference in context.  This all happens in the IonRouterOutlet component, but when this component renders, it often causes its children (your routes and IonPages) to render along with it.&lt;/p&gt;

&lt;p&gt;This is why you might see an IonPage render two or three times when it is displayed the first time.&lt;/p&gt;

&lt;p&gt;Next, you might notice that some pages might render when they are not even in the current view.&lt;/p&gt;

&lt;p&gt;To provide some of the smooth transitions and to maintain the state of views that you left but might come back to, we don't actually unmount your component in some scenarios (like navigating between tabs). Instead, when your page transitions out of view, we hide it via CSS. The component is still mounted and can still render. Therefore, if the component gets any new props passed into it, it will render.&lt;/p&gt;

&lt;p&gt;By default, the routes are setup to pass in the your IonPage in the component prop of a route, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/tab1"&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Tab1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;exact&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When using the component prop, React Router will pass in some props on your behalf, like &lt;code&gt;location&lt;/code&gt; and &lt;code&gt;history&lt;/code&gt;. Each time you make a navigation change, these route props will change, which will cause all your IonPages that are currently mounted to render again.&lt;/p&gt;

&lt;p&gt;This can get a bit out of hand, so let’s take a look at a few strategies to cut down on the excessive renders.&lt;/p&gt;

&lt;h2&gt;
  
  
  Optimizing the renders
&lt;/h2&gt;

&lt;p&gt;So there are two main culprits here. Parent components that are rendering that cause its children to render, and new props being passed in via routing that causes another render.&lt;/p&gt;

&lt;p&gt;Let's deal with parent components rendering first.&lt;/p&gt;

&lt;h3&gt;
  
  
  Component Memoization
&lt;/h3&gt;

&lt;p&gt;In React class-based components, we were able to finely control when components would render with the &lt;code&gt;shouldComponentUpdate&lt;/code&gt; lifecycle method. This method would receive the new props/state coming in, which we could compare to the old props/state and determine if we want our component to call its render method. Or, even better, we could inherit from &lt;code&gt;React.PureComponent&lt;/code&gt; and let React take care of this logic for us.&lt;/p&gt;

&lt;p&gt;This would make it so that your component would only update if its props or state change, and ignore any updates from the parent component rendering.&lt;/p&gt;

&lt;p&gt;To accomplish something similar in a React Functional Component (FC), we can wrap our FC in &lt;code&gt;React.memo&lt;/code&gt;, which will &lt;a href="https://en.wikipedia.org/wiki/Memoization" rel="noopener noreferrer"&gt;memoize&lt;/a&gt; your component and store a cached version of it based on the props that are passed into it.&lt;/p&gt;

&lt;p&gt;To do so, I like to wrap the FC as its being exported with &lt;code&gt;React.memo&lt;/code&gt; like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Tab1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should notice that now the number of renders is cut down quite a bit when you navigate between the tabs.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;React.memo&lt;/code&gt; is a good way to cut down on needless renders, however, take care when doing this, as you are basically trading fewer renders for memory consumption.&lt;/p&gt;

&lt;h3&gt;
  
  
  Route Setup
&lt;/h3&gt;

&lt;p&gt;Next, let’s modify our routes so that React Router no longer passes in the Route Component props into our Tab1 page.&lt;/p&gt;

&lt;p&gt;In the route setup, we are using the &lt;code&gt;component&lt;/code&gt; prop, and React Router will pass in all the route props every time there is a change in navigation. &lt;/p&gt;

&lt;p&gt;As of React Router 5.1, there is a new method to specify which component to render when the route matches, &lt;a href="https://reacttraining.com/blog/react-router-v5-1/#staying-ahead-of-the-curve" rel="noopener noreferrer"&gt;and this method is encouraged going forward&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The new method is to pass your component in as a child to the route like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/tab1"&lt;/span&gt; &lt;span class="na"&gt;exact&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Tab1&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if you check the logs, you will see that the &lt;code&gt;Tab1&lt;/code&gt; page only renders once on its initial load, and has no additional renders when navigating between the tabs. Nice 🎉!&lt;/p&gt;

&lt;p&gt;"But what if I need the routing props in my component?" I hear you ask.&lt;/p&gt;

&lt;p&gt;React Router has you covered there as well. There are several new &lt;a href="https://reacttraining.com/blog/react-router-v5-1/#meet-react-router-51" rel="noopener noreferrer"&gt;React Hooks available&lt;/a&gt; that you can use to get access to the same props that were passed in before, namely &lt;code&gt;useParams&lt;/code&gt;, &lt;code&gt;useLocation&lt;/code&gt;, and &lt;code&gt;useHistory&lt;/code&gt;. So if you had a route setup to get an &lt;code&gt;id&lt;/code&gt; param from the path, you would access it like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* The Route: */&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/tab1/:id"&lt;/span&gt; &lt;span class="na"&gt;exact&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Tab1&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="cm"&gt;/* And inside the Tab1.tsx function: */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useParams&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// do something with params.id&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Wrapping Up
&lt;/h3&gt;

&lt;p&gt;With just a few quick optimizations, we were able to cut down the renders from many times on page navigation, to just a single time when the IonPage first loads. Not too shabby!&lt;/p&gt;

&lt;p&gt;Got any comments or want to see me cover something around Ionic React in the future? Hit me up in the comments below or catch me on Twitter &lt;a href="https://www.twitter.com/elylucas" rel="noopener noreferrer"&gt;@elylucas&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>ionic</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The Easiest Way for Web Developers to Build Mobile Apps</title>
      <dc:creator>Max Lynch</dc:creator>
      <pubDate>Tue, 05 Jan 2021 15:45:13 +0000</pubDate>
      <link>https://dev.to/ionic/the-easiest-way-for-web-developers-to-build-mobile-apps-1ih8</link>
      <guid>https://dev.to/ionic/the-easiest-way-for-web-developers-to-build-mobile-apps-1ih8</guid>
      <description>&lt;p&gt;For web developers interested in building Mobile apps, there's a plethora of options today. Developers can choose between projects like React Native, NativeScript, Cordova, Ionic Framework, and Capacitor, just to name a few.&lt;/p&gt;

&lt;p&gt;Given the large number of options, it's not always clear  what would be the most appropriate for a web developer looking for a familiar web-based development experience.&lt;/p&gt;

&lt;p&gt;With that, I'd like to make the case that &lt;a href="https://capacitorjs.com/" rel="noopener noreferrer"&gt;Capacitor&lt;/a&gt; (optionally with a mobile-focused UI framework like &lt;a href="https://ionicframework.com/" rel="noopener noreferrer"&gt;Ionic Framework&lt;/a&gt;) is the most natural and easiest way that web developers can build mobile apps.&lt;/p&gt;

&lt;h2&gt;
  
  
  "Electron for Mobile"
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://electronjs.org/" rel="noopener noreferrer"&gt;Electron&lt;/a&gt; is a massively popular solution for building cross-platform desktop applications using standard web technologies. Web Developers can use the standard HTML, CSS, and JavaScript they use for web apps, including any popular libraries like React/Angular/Vue, Tailwind, or Material UI, and turn those apps into powerful desktop apps.&lt;/p&gt;

&lt;p&gt;This simple formula has turned Electron into one of the most popular cross-platform toolkits. Today, Electron powers many popular apps, like Slack and VS Code.&lt;/p&gt;

&lt;p&gt;If you ever find yourself asking "what is the analog to Electron but for mobile apps?" the answer is &lt;a href="https://capacitorjs.com/" rel="noopener noreferrer"&gt;Capacitor&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Like Electron, Capacitor takes a standard web app that runs in the browser, and extends it with access to powerful native APIs and Native UI (like &lt;a href="https://capacitorjs.com/docs/apis/camera" rel="noopener noreferrer"&gt;Camera&lt;/a&gt; and &lt;a href="https://capacitorjs.com/docs/apis/filesystem" rel="noopener noreferrer"&gt;Filesystem&lt;/a&gt;). These APIs work on iOS, Android, Web, and Electron.&lt;/p&gt;

&lt;p&gt;While Electron bundles in a "web view" through Chromium, Capacitor uses the standard embedded Web View native controls available on iOS and Android. This means that Capacitor doesn't suffer from the same bloat issues that Electron does.&lt;/p&gt;

&lt;p&gt;The net effect is that Capacitor is really a sort of  "Electron for Mobile."&lt;/p&gt;

&lt;h2&gt;
  
  
  What about React Native or Flutter?
&lt;/h2&gt;

&lt;p&gt;You might be asking yourself: why isn't React Native (or Flutter) the "Electron for Mobile?"&lt;/p&gt;

&lt;p&gt;The reason is that React Native and Flutter do not use a standard web browser environment to run an app. Rather, they are abstractions over system UI controls and APIs to provide a "web-like" experience building apps rather than a true web environment. Both require code specifically written for each platform, and cannot use web-specific libraries or code.&lt;/p&gt;

&lt;p&gt;This is important, because it means the shortest path for a web developer to build a mobile app is Capacitor, hands down:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fy47oq2g4ida5ztgdhvsu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fy47oq2g4ida5ztgdhvsu.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  An Example
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftq6nt1p40o4877d7664w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftq6nt1p40o4877d7664w.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's take a &lt;a href="https://github.com/mlynch/ionic-react-example" rel="noopener noreferrer"&gt;simple example&lt;/a&gt; of a web app using Ionic Framework with React for a native-quality mobile UI experience, and Capacitor to deploy it natively to iOS, Android, and web.&lt;/p&gt;

&lt;p&gt;Taking a look at the &lt;a href="https://github.com/mlynch/ionic-react-example" rel="noopener noreferrer"&gt;code&lt;/a&gt;, we see that it's just a plain React app that happens to use Ionic Framework for its UI components. For example, developers familiar with React Router should find the &lt;a href="https://github.com/mlynch/ionic-react-example/blob/master/src/App.tsx#L37" rel="noopener noreferrer"&gt;JSX used to build the Tab layout&lt;/a&gt; familiar.&lt;/p&gt;

&lt;p&gt;Then, by running some Capacitor commands, we can bundle the app and run it right in Xcode:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsnmo35hui27kz7mqmdhn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsnmo35hui27kz7mqmdhn.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since our app is just a plain React app, we can also run it directly in the browser and even deploy it as a Progressive Web App to any static web host:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9j9p4mb9x0d6oei667oh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9j9p4mb9x0d6oei667oh.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, Capacitor ships with a JS module, &lt;code&gt;@capacitor/core&lt;/code&gt;, that provides a consistent, cross-platform approach to accessing device functionality. &lt;/p&gt;

&lt;p&gt;For example, to access the &lt;code&gt;Filesystem&lt;/code&gt; API, we can use the same code on iOS, Android, Web, and Electron:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;p&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;br&gt;
  &lt;span class="nx"&gt;Plugins&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;br&gt;
  &lt;span class="nx"&gt;FilesystemDirectory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br&gt;
  &lt;span class="nx"&gt;FilesystemEncoding&lt;/span&gt;&lt;br&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@capacitor/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Filesystem&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Plugins&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;fileWrite&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;br&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;br&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Filesystem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFile&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;secrets/text.txt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This is a test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FilesystemDirectory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Documents&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;encoding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FilesystemEncoding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UTF8&lt;/span&gt;&lt;br&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;&lt;br&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Wrote file&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;br&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;br&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unable to write file&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;br&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;&lt;br&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Who's using Capacitor?&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;Capacitor is being used to power major apps today. Companies like Burger King, Popeyes, and the BBC (who wrote a &lt;a href="https://medium.com/bbc-design-engineering/shipping-progressive-web-apps-everywhere-190a421c606a" rel="noopener noreferrer"&gt;great article&lt;/a&gt;  about their use of Capacitor to build universal, web-native apps) are using Capacitor build apps across iOS, Android, Web, and Desktop with one code base and standard web technology.&lt;/p&gt;

&lt;p&gt;Capacitor is also the new native foundation of &lt;a href="https://ionicframework.com/" rel="noopener noreferrer"&gt;Ionic Framework&lt;/a&gt;, which powers over 15% of all apps in the app store today.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started with Capacitor
&lt;/h2&gt;

&lt;p&gt;If you're familiar with Electron, Capacitor should feel very familiar to you. It's installed like a typical JS module directly into your app, and a local CLI tool is added for copying your web app to native iOS and Android projects, as well as syncing and installing new Capacitor plugins.&lt;/p&gt;

&lt;p&gt;To get started with Capacitor, check out the official &lt;a href="https://capacitorjs.com/docs" rel="noopener noreferrer"&gt;Capacitor Docs&lt;/a&gt; and get building!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>ionic</category>
    </item>
    <item>
      <title>Ionic Vue: The UI library for Vue 3</title>
      <dc:creator>Matt Netkow</dc:creator>
      <pubDate>Fri, 20 Nov 2020 17:04:11 +0000</pubDate>
      <link>https://dev.to/ionic/ionic-vue-the-ui-library-for-vue-3-7m5</link>
      <guid>https://dev.to/ionic/ionic-vue-the-ui-library-for-vue-3-7m5</guid>
      <description>&lt;p&gt;The Vue team &lt;a href="https://news.vuejs.org/issues/186" rel="noopener noreferrer"&gt;released Vue 3 in September&lt;/a&gt; to much-deserved fanfare. With improved performance, smaller bundle sizes, new APIs, and a revamped foundation to support future framework iterations, it’s no wonder the Vue community is excited.&lt;/p&gt;

&lt;p&gt;Unfortunately, many UI libraries aren’t compatible with Vue 3 yet. If you’re looking for one that is production-ready right now, then check out &lt;a href="https://ionicframework.com/docs/vue/quickstart" rel="noopener noreferrer"&gt;Ionic Vue&lt;/a&gt;, a UI library with over 100 mobile and desktop components built for Vue 3. Let’s take a look at everything it has to offer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ionic Vue: A Native Vue version of Ionic Framework
&lt;/h2&gt;

&lt;p&gt;Ionic Framework is an open-source UI toolkit focused on building high-quality apps for native iOS, native Android, and the web! It’s built from the ground up with HTML, CSS, and JavaScript, so web developers should feel right at home. The components allow developers to build native experiences, all while using web technology. Now used by millions of developers, Ionic &lt;a href="https://appfigures.com/top-sdks/development" rel="noopener noreferrer"&gt;powers &amp;gt; 15% of all&lt;/a&gt; app store apps.&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%2Fi%2Fynoy3eko4qzkmme0h3u2.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%2Fi%2Fynoy3eko4qzkmme0h3u2.png" alt="Ionic Vue music app example" width="800" height="720"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ionic Vue is the native Vue version of Ionic Framework. It acts as a wrapper for the core UI component library (aptly named &lt;code&gt;@ionic/core&lt;/code&gt;), allowing Ionic to support all Vue 3 features with ease. Here’s the entry point of an Ionic Vue app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Vue 3 component definition&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IonApp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;IonRouterOutlet&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@ionic/vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;App&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;IonApp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;IonRouterOutlet&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Template with Ionic Framework UI components --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ion-app&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ion-router-outlet&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/ion-app&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, it’s written in modern web code. Ionic likes to say that you don’t &lt;em&gt;learn&lt;/em&gt; Ionic, per se - you leverage your existing web development skills to build apps using their UI components.&lt;/p&gt;

&lt;h2&gt;
  
  
  Production Ready for Vue 3
&lt;/h2&gt;

&lt;p&gt;The Ionic team released Ionic Vue shortly after the launch of Vue 3. Other libraries are still implementing Vue 3 support, so how was Ionic able to ship so fast? The answer: All Ionic Framework UI components are web components consumed by web developers using official framework bindings (including Angular, React, Vue, and basically any other JavaScript framework on the market today, or tomorrow). Developers using each framework get the experience they are familiar with, such as the framework’s routing system, lifecycle events, official APIs and tooling, and more. Frankly, it’s a win-win! Learn more about how Ionic accomplished their “Ionic for Everyone” milestone &lt;a href="https://ionicframework.com/blog/introducing-ionic-4-ionic-for-everyone/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That’s not all. Ever wish you could use your favorite UI library on multiple platforms but couldn’t because they didn’t leverage each platform’s specific design language? You’re in luck. Every Ionic component &lt;a href="https://ionicframework.com/docs/core-concepts/fundamentals#adaptive-styling" rel="noopener noreferrer"&gt;adapts its look&lt;/a&gt; to the platform the app is running on, such as Cupertino on iOS and Material Design on Android. Through these subtle design changes between platforms, developers achieve a native look and feel while users are happy to receive a high-quality app experience. This adaptation is applied automatically and is entirely configurable should you wish to make theming changes to fit your brand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;Creating a Vue 3-powered Ionic app is a breeze. Begin by installing the Ionic CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @ionic/cli@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, create an Ionic Vue application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ionic start my-vue-app &lt;span class="nt"&gt;--type&lt;/span&gt; vue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After answering a few questions, you can start a local development server with &lt;code&gt;ionic serve&lt;/code&gt;. This command uses the Vue CLI to compile your app, start a dev server, and open your app in a new browser window.&lt;/p&gt;

&lt;p&gt;From here, you can explore Ionic’s &lt;a href="https://ionicframework.com/docs/components" rel="noopener noreferrer"&gt;100+ UI components&lt;/a&gt; or take the &lt;a href="https://ionicframework.com/docs/vue/your-first-app" rel="noopener noreferrer"&gt;“First App” tutorial&lt;/a&gt; that covers Ionic’s core app development concepts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Ionic Vue to an Existing Vue 3 App
&lt;/h2&gt;

&lt;p&gt;If you’ve already started working on a Vue 3 app, you can add in Ionic Framework components. First, install two packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @ionic/vue @ionic/vue-router
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, add the &lt;code&gt;IonicVue&lt;/code&gt; package into your app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// main.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IonicVue&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@ionic/vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./App.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;IonicVue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isReady&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, there are some small &lt;a href="https://ionicframework.com/docs/intro/cdn#routing" rel="noopener noreferrer"&gt;routing and CSS changes&lt;/a&gt; to make. Once those steps are complete, you can start &lt;a href="https://ionicframework.com/docs/components" rel="noopener noreferrer"&gt;adding Ionic’s components&lt;/a&gt; to your Vue 3 app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus: Deploy your Vue 3 app to mobile
&lt;/h2&gt;

&lt;p&gt;You’ve built a great Vue 3 app that works well on the web and desktop. What about native mobile? Once again, Ionic has you covered. With &lt;a href="https://capacitorjs.com/" rel="noopener noreferrer"&gt;Capacitor&lt;/a&gt;, Ionic’s official cross-platform native runtime, you can deploy your Vue 3 apps as progressive web apps &lt;em&gt;and&lt;/em&gt; iOS/Android apps, all from the same codebase.&lt;/p&gt;

&lt;p&gt;Capacitor also provides APIs with functionality covering all three platforms. Here’s the Geolocation API, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Capacitor Geolocation plugin example&lt;/span&gt;
&lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;locationData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getLocation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Geolocation&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Plugins&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Geolocation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getCurrentPosition&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;locationData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;long&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;longitude&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;locationData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getLocation&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ion-button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"getLocation()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Where am I?&lt;span class="nt"&gt;&amp;lt;/ion-button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;{{ locationData }}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that there’s no separate logic for each platform (“web,” “iOS,” or “Android”) in the code. That’s because Capacitor automatically detects the platform the app is running on then calls the appropriate native layer code. With Core APIs like these, coupled with full access to native SDKs and a growing roster of &lt;a href="https://capacitorjs.com/community" rel="noopener noreferrer"&gt;community-supported plugins&lt;/a&gt;, Capacitor empowers you to build truly native mobile apps from your Vue 3 projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start Building awesome Vue 3 apps for web and mobile
&lt;/h2&gt;

&lt;p&gt;If you’ve been holding off from trying Vue 3 until more libraries become compatible, now’s a great time to give Ionic Vue a try. With Ionic, you can build a fully-featured app then deploy it to multiple platforms with Capacitor.&lt;/p&gt;

&lt;p&gt;For a more in-depth look at Ionic Vue, we recommend checking our &lt;a href="https://ionicframework.com/docs/vue/quickstart" rel="noopener noreferrer"&gt;Quickstart Guide&lt;/a&gt;. For a more hands-on experience, take a look at our &lt;a href="https://ionicframework.com/docs/vue/your-first-app" rel="noopener noreferrer"&gt;Build Your First App Guide&lt;/a&gt;. If you already have a Vue 3 app, &lt;a href="https://capacitorjs.com/docs/getting-started#adding-capacitor-to-an-existing-web-app" rel="noopener noreferrer"&gt;bring it to iOS and Android with Capacitor&lt;/a&gt;. Built something neat? Share your Ionic Vue app with us over &lt;a href="https://twitter.com/IonicFramework" rel="noopener noreferrer"&gt;@IonicFramework&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>vue</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>ionic</category>
    </item>
    <item>
      <title>What is it about Vue?</title>
      <dc:creator>Max Lynch</dc:creator>
      <pubDate>Mon, 19 Oct 2020 16:06:24 +0000</pubDate>
      <link>https://dev.to/ionic/what-is-it-about-vue-1j7n</link>
      <guid>https://dev.to/ionic/what-is-it-about-vue-1j7n</guid>
      <description>&lt;p&gt;On the heels of announcing &lt;a href="https://ionicframework.com/blog/announcing-ionic-vue/" rel="noopener noreferrer"&gt;official Vue support for Ionic Framework&lt;/a&gt;, I wanted to dig into why we decided to officially support Vue here at Ionic, and why we’re so excited about it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;But first, if you aren’t familiar with Ionic, we make popular open source projects like &lt;a href="https://ionicframework.com/" rel="noopener noreferrer"&gt;Ionic Framework&lt;/a&gt; and &lt;a href="https://capacitorjs.com/" rel="noopener noreferrer"&gt;Capacitor&lt;/a&gt;, focused on enabling web developers to build award winning mobile apps with their existing web development skills and libraries. Ionic Framework provides a cross-platform UI toolkit focused on the visual aspect of a quality mobile experience, and Capacitor provides a cross-platform runtime and plugin API to access the full native functionality your app needs on each platform it runs on. Use them together or use Capacitor with any web-based UI framework for mobile!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Many developers know Ionic Framework as a mobile toolkit for Angular. And while we fully support Angular today, in the last few years we’ve branched out to supporting React, and now Vue.&lt;/p&gt;

&lt;p&gt;It’s no small task for us to officially support a framework. While Ionic Framework’s web components work in any web technology, integration with framework-specific tooling like Routers, CLIs, and more is where the bulk of the work comes, so choosing to support a framework officially is a big deal for us.&lt;/p&gt;

&lt;p&gt;Why, then, do we feel it is crucial to support Vue? And why do we feel that Ionic Framework + Vue brings unique value to the ecosystem and an experience that lives up to our goals as a project?&lt;/p&gt;

&lt;h2&gt;
  
  
  “The best of React and Angular”
&lt;/h2&gt;

&lt;p&gt;Ionic Framework was initially built around AngularJS (that’s the 1.x version) back in 2013. What drew us to AngularJS back then was the ability to incrementally adopt it in any web app, extend HTML with powerful control flow constructs (loops, conditionals, etc), create essentially new HTML tags powered by JS, and easily apply it to any size app from small to enterprise-scale.&lt;/p&gt;

&lt;p&gt;While Angular 2 evolved from the original approach taken in AngularJS, doubling down on its focus on large, complex enterprise apps (the kind Google and other large companies build), those original features of AngularJS that drew so many to it in the beginning fell out of favor in exchange for a monolithic solution focused on building large apps from scratch.&lt;/p&gt;

&lt;p&gt;When talking to Vue developers, one way they frame why Vue is so great is it essentially perfected that early approach in AngularJS, creating something fundamentally new and compelling along the way. It’s no surprise then that so many Ionic 1.x developers who used AngularJS back then were drawn to Vue when the Angular 2 fork in the road appeared, and picked it up very quickly.&lt;/p&gt;

&lt;p&gt;Vue developers often contrast it with React as well, appreciating more powerful data binding (especially with forms), compilation-free templating that uses standard HTML (i.e. no JSX required), and the batteries-included approach where key libraries for routing and state management are officially supported and maintained by the Vue team.  &lt;/p&gt;

&lt;p&gt;Add these up and it’s clear why many Vue developers consider it to be the best of both worlds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vue is exploding
&lt;/h2&gt;

&lt;p&gt;With all the benefits above, it’s no wonder that Vue has found itself a passionate developer base that wasn’t satisfied with the binary Angular or React decision tree and tradeoffs.&lt;/p&gt;

&lt;p&gt;That developer base is absolutely exploding, with some metrics, like stars, growing faster than React and nearly any other project on GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fuc1n8ct6otb6chp1wxqo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fuc1n8ct6otb6chp1wxqo.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While stars are a vanity metric, there’s proof that this popularity has fostered a strong ecosystem of Vue-specific addons, projects, and frameworks. Vue-specific web app frameworks like Nuxt.js and Gridsome add powerful Jamstack features to the Vue ecosystem. UI libraries like Vuetify, and mobile solutions like Quasar, NativeScript, and Ionic Vue provide options for building engaging UI experiences with Vue across nearly any platform.&lt;/p&gt;

&lt;p&gt;It’s clear that Vue is a force to be reckoned with and any web library like Ionic that purports to support the key frameworks web developers are using simply has to take it very seriously.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ionic Framework and Vue is a perfect match
&lt;/h2&gt;

&lt;p&gt;One of the most common questions we received over the last two years has been “when is Vue support for Ionic Framework coming out?” In fact, we received that question so often that it became a meme inside the company, with us often taking bets on how long it would take for someone to ask about Vue support on any given tweet or blog post (even if it had nothing to do with Vue!)&lt;/p&gt;

&lt;p&gt;Obviously, the Vue ecosystem has been hungry for more mobile app development solutions. While a few solutions already exist for building mobile apps with Vue, including NativeScript Vue and Vue Native, what Ionic Framework brings to the table is a mobile development solution that is much more web centric. When you build with Ionic Vue, you’re able to target native iOS and Android with a &lt;a href="https://medium.com/@maxlynch/cordova-ionic-apps-are-native-apps-64f9e1a995d9" rel="noopener noreferrer"&gt;truly native app&lt;/a&gt; that gives you full access to the native device and any native API. At the same time, you get the benefit of a UI layer that is truly web, so any existing web libraries, vue add-ons, UI components, or CSS styles will fit right into your Ionic Vue mobile app. Plus, as a bonus you can deploy your Ionic Vue mobile apps as pure mobile web apps or PWAs.&lt;/p&gt;

&lt;p&gt;Ionic is focused intensely on web developers using popular web development technologies, with a massive community, and with support and features for serious apps and enterprise teams. To add on to that, Ionic Framework is backed by a &lt;a href="https://ionic.io/" rel="noopener noreferrer"&gt;growing company&lt;/a&gt; that is focused exclusively on commercializing Ionic Framework and its companion native runtime project, Capacitor. &lt;/p&gt;

&lt;p&gt;From a developer experience standpoint, Ionic and Vue have similar roots. Both were inspired by AngularJS to some extent, and both focus on empowering web developers to build incredible things with the technologies they already know, with a low barrier to entry. Vue’s approach of using standard HTML in templates pairs incredibly well with Ionic Framework’s move to Web Components at the core, so using Ionic components feels like any other HTML tag, only with magic mobile powers.&lt;/p&gt;

&lt;p&gt;Finally, Ionic is immensely popular, powering &lt;a href="https://appfigures.com/top-sdks/development/apps" rel="noopener noreferrer"&gt;nearly 15% of all app stores&lt;/a&gt;, and has become synonymous with “mobile for web developers.”&lt;/p&gt;

&lt;h2&gt;
  
  
  The future is Bright for Vue
&lt;/h2&gt;

&lt;p&gt;The technical challenges and long term maintenance concerns that come with choosing to officially support a framework for Ionic Framework are significant. We will invest considerable resources, financial and otherwise, to support any new framework integration in Ionic Framework.&lt;/p&gt;

&lt;p&gt;We have decided to fully embrace and support Vue starting with Vue 3, because we think it is increasingly a pillar of the web development ecosystem, and will only grow in importance and relevance over time.&lt;/p&gt;

&lt;p&gt;We also think it spiritually aligns incredibly well with our values and approach with Ionic Framework. We believe in the web platform. We believe in enhancing HTML, CSS, and JavaScript and enabling web developers to do incredible new things with it. Vue helps teams build and orchestrate the functionality and rendering of their app, and Ionic Vue helps those teams make their Vue apps feel great on mobile.&lt;/p&gt;

&lt;p&gt;If you’re curious about Ionic Vue and want to try building iOS, Android, and Progressive Web Apps using Vue 3 and all the Vue-compatible web libraries you know and love, take a look at &lt;a href="https://ionicframework.com/docs/vue/quickstart" rel="noopener noreferrer"&gt;Ionic Vue&lt;/a&gt;!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hey, you there! Want to build a mobile app with Vue but already have a UI library or can't use Ionic Framework's UI controls? Check out &lt;a href="https://capacitorjs.com/" rel="noopener noreferrer"&gt;Capacitor&lt;/a&gt;. It's the native runtime part of the Ionic stack that runs any web app on mobile regardless of what it was built with.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>vue</category>
      <category>ionic</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Announcing Ionic Vue</title>
      <dc:creator>Liam DeBeasi</dc:creator>
      <pubDate>Thu, 15 Oct 2020 17:21:33 +0000</pubDate>
      <link>https://dev.to/ionic/announcing-ionic-vue-314f</link>
      <guid>https://dev.to/ionic/announcing-ionic-vue-314f</guid>
      <description>&lt;p&gt;Today I am thrilled to announce the release of Ionic Vue, a native Vue version of Ionic Framework that makes it easy to build apps for iOS, Android, and the web as a Progressive Web App. Ionic Vue has been written to take advantage of all the great new features that recently shipped in Vue 3.&lt;/p&gt;

&lt;p&gt;Ionic Vue represents a big milestone in Ionic Framework's development after the release of our &lt;a href="https://ionicframework.com/blog/announcing-ionic-react/" rel="noopener noreferrer"&gt;React integration&lt;/a&gt; earlier in 2020. This launch is the culmination of our “&lt;a href="https://ionicframework.com/blog/introducing-ionic-4-ionic-for-everyone/" rel="noopener noreferrer"&gt;Ionic for Everyone&lt;/a&gt;” push that was kicked off in early 2019 with the release of Ionic Framework v4. As a result, I'd like to share some context as to how we got here and where we are going next.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ionicframework.com/docs/vue/quickstart" rel="noopener noreferrer"&gt;Click here&lt;/a&gt; if you just want to get started building with Ionic Vue, I won't be offended. 😊&lt;/p&gt;

&lt;h2&gt;
  
  
  A bit about Ionic Framework 💁‍♀️
&lt;/h2&gt;

&lt;p&gt;If this is your first time hearing about Ionic, Hello there! 👋&lt;/p&gt;

&lt;p&gt;Ionic Framework is an open source UI toolkit focused on building high quality mobile apps for native iOS, native Android, and the web! From the ground up, it's built with HTML, CSS, and JavaScript, so web developers should feel right at home building with our components. Our components allow developers to build native experiences, all while using web technology. Today, Ionic powers &lt;a href="https://appfigures.com/top-sdks/development/apps" rel="noopener noreferrer"&gt;&amp;gt; 15% of all apps&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.ionicframework.com%2Fwp-content%2Fuploads%2F2020%2F10%2Fionic-app-light.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.ionicframework.com%2Fwp-content%2Fuploads%2F2020%2F10%2Fionic-app-light.png" alt="an Ionic app in light mode"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.ionicframework.com%2Fwp-content%2Fuploads%2F2020%2F10%2Fionic-app-dark.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.ionicframework.com%2Fwp-content%2Fuploads%2F2020%2F10%2Fionic-app-dark.png" alt="an Ionic app in dark mode"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A Brief History 📖
&lt;/h2&gt;

&lt;p&gt;You might recall us releasing an Ionic Vue beta back in early 2019. That version was built for Vue 2 and lacked features such as proper &lt;code&gt;v-model&lt;/code&gt; support. While developing Ionic Vue and Ionic React side by side, we quickly realized they had a lot in common. In fact, we found ourselves implementing similar features and fixing the same bugs multiple times.&lt;/p&gt;

&lt;p&gt;Also around this time, the Vue team was starting to ramp up development on Vue 3, and we decided it made sense for Ionic Framework to support that version instead. We paused Ionic Vue development and shifted focus to Ionic React. With its completion, we found ourselves with all the key learnings we needed to develop Ionic Vue, and we are really happy with the way it turned out… if we may say so ourselves.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Big Milestone 🏆
&lt;/h2&gt;

&lt;p&gt;Since its launch in January 2019, we wanted Ionic Framework v4 to be known as &lt;em&gt;the&lt;/em&gt; app framework for every web developer. To that extent, we lovingly referred to Ionic Framework v4 as "Ionic for Everyone." This release rebuilt Ionic Framework from the ground up with Web Components. While this change took time, it ultimately allows us to support any framework without having to re-write Ionic Framework.&lt;/p&gt;

&lt;p&gt;Today, we are committed to supporting not just Angular, but also React and Vue. In a sense, the release of Ionic Vue is an indication that our efforts have paid off. Neither the React nor the Vue integrations required any major rewrites of Ionic Framework, and the Ionic API remains remarkably similar across framework integrations.&lt;/p&gt;

&lt;p&gt;The release of Ionic Vue demonstrates that any web developer can build performant, cross platform applications with Ionic Framework using the framework of their choice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started 🏃‍♂️
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: The first official version of Ionic Vue is v5.4.0&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Getting started with Ionic Vue is a breeze. First, be sure you have the latest version of the Ionic CLI installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @ionic/cli@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;If you used the Ionic Vue beta, be sure to update your CLI as you likely were using a pre-release version.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;From here, we can use the Ionic CLI to create an Ionic Vue starter application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ionic start my-vue-app &lt;span class="nt"&gt;--type&lt;/span&gt; vue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CLI will guide you through the setup process by first asking a few questions. Once the application has been installed, you can start the development server by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ionic serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Under the hood, the &lt;code&gt;ionic serve&lt;/code&gt; command uses the Vue CLI to compile your app, start a dev server, and open your app in a new browser window.&lt;/p&gt;

&lt;p&gt;From here, we have access to all of Ionic Framework's components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ion-page&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ion-header&lt;/span&gt; &lt;span class="na"&gt;:translucent=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;ion-toolbar&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;ion-title&amp;gt;&lt;/span&gt;Hello Vue&lt;span class="nt"&gt;&amp;lt;/ion-title&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/ion-toolbar&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ion-header&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;ion-content&lt;/span&gt; &lt;span class="na"&gt;:fullscreen=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;ion-header&lt;/span&gt; &lt;span class="na"&gt;collapse=&lt;/span&gt;&lt;span class="s"&gt;"condense"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;ion-toolbar&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;ion-title&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;"large"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Hello Vue&lt;span class="nt"&gt;&amp;lt;/ion-title&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/ion-toolbar&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/ion-header&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ion-content&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/ion-page&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;IonContent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;IonHeader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;IonPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;IonTitle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;IonToolbar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@ionic/vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;HomePage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;IonContent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;IonHeader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;IonPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;IonTitle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;IonToolbar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To use the components, you need to import them from the &lt;code&gt;@ionic/vue&lt;/code&gt; package and provide them to your Vue component.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building upon the Vue Router 🧭
&lt;/h3&gt;

&lt;p&gt;Like with the Angular and React versions of Ionic Framework, we chose to use the official router that is provided with Vue, &lt;code&gt;vue-router&lt;/code&gt;. To handle Ionic Framework’s animations, we have extended the Router’s API through the &lt;code&gt;ion-router-outlet&lt;/code&gt; component. This component is used in place of the typical &lt;code&gt;router-view&lt;/code&gt; component that is used in Vue applications.&lt;/p&gt;

&lt;p&gt;Using this modified router is mostly the same as the regular &lt;code&gt;vue-router&lt;/code&gt; except with a few different imports. Lazy loading works out of the box too!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createWebHistory&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@ionic/vue-router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Home&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/views/Home.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createRouter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;createWebHistory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BASE_URL&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/home&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/home&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Home&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Home&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/lazy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/views/Lazy.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rather than import &lt;code&gt;createRouter&lt;/code&gt; and &lt;code&gt;createWebHistory&lt;/code&gt; from &lt;code&gt;vue-router&lt;/code&gt;, you need to import them from &lt;code&gt;@ionic/vue-router&lt;/code&gt;. These imports wrap the &lt;code&gt;vue-router&lt;/code&gt; functions of the same name and provide a few additional details that let Ionic Framework work well within the Vue environment.&lt;/p&gt;

&lt;p&gt;While we recommend relying on the tooling that Vue Router provides, we have added support for the &lt;code&gt;router-link&lt;/code&gt; property on components that allow for it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ion-item&lt;/span&gt; &lt;span class="na"&gt;router-link=&lt;/span&gt;&lt;span class="s"&gt;"/child-page"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ion-label&amp;gt;&lt;/span&gt;Click Me to Navigate&lt;span class="nt"&gt;&amp;lt;/ion-label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ion-item&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also specify the direction using &lt;code&gt;router-direction&lt;/code&gt; and a custom animation using &lt;code&gt;router-animation&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For transitions and lifecycle events to work properly, each Ionic page must be wrapped in an &lt;code&gt;ion-page&lt;/code&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ion-page&amp;gt;&lt;/span&gt; ... &lt;span class="nt"&gt;&amp;lt;/ion-page&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IonPage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@ionic/vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;HomePage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IonPage&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lifecycle events can be accessed by providing the appropriate event as a method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;HomePage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;IonPage&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;ionViewDidEnter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;ionViewDidLeave&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;ionViewWillEnter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;ionViewWillLeave&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Doing Things the Vue Way 🛠
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;@ionic/vue&lt;/code&gt; includes support for every Ionic Framework component except for virtual scroll. We are embracing the community-driven solutions for virtual scroll in Vue applications and will be providing more information on how to get started with these solutions soon! Using components in Ionic Vue will still feel familiar, but will use Vue’s template syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ion-input&lt;/span&gt; &lt;span class="na"&gt;v-model=&lt;/span&gt;&lt;span class="s"&gt;"inputValueRef"&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;ionInput=&lt;/span&gt;&lt;span class="s"&gt;"onChange($event)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/ion-input&amp;gt;&lt;/span&gt;
  Value: { inputValueRef }
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IonInput&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@ionic/vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MyComponent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IonInput&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CustomEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inputValueRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;inputValueRef&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Overlay components, such as &lt;code&gt;ion-modal&lt;/code&gt;, can be created dynamically by importing the appropriate controller from &lt;code&gt;@ionic/vue&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ion-page&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ion-content&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;ion-button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"openModal()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Open Modal&lt;span class="nt"&gt;&amp;lt;/ion-button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ion-content&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/ion-page&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IonButton&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;IonContent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;IonPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;modalController&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@ionic/vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ModalExample&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/components/Modal.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;HomePage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IonButton&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;IonContent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;IonPage&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;openModal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;modal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;modalController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ModalExample&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;modal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;present&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;openModal&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Overlay components can also be used directly in your component's template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ion-page&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ion-content&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;ion-button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"setModal(true)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Open Modal&lt;span class="nt"&gt;&amp;lt;/ion-button&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;ion-modal&lt;/span&gt; &lt;span class="na"&gt;:is-open=&lt;/span&gt;&lt;span class="s"&gt;"isOpen"&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;onDidDismiss=&lt;/span&gt;&lt;span class="s"&gt;"setModal(false)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;ModalExample&amp;gt;&amp;lt;/ModalExample&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/ion-modal&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ion-content&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/ion-page&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IonButton&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;IonContent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;IonModal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;IonPage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@ionic/vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ModalExample&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/components/Modal.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;HomePage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ModalExample&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;IonButton&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;IonContent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;IonModal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;IonPage&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isOpen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;setModal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isOpen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setModal&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Building your way with either TypeScript or JavaScript ✌️
&lt;/h3&gt;

&lt;p&gt;We love TypeScript at Ionic, and have believed for quite some time now that it’s a great tool for building scalable apps. That said, we know how much the Vue community values simplicity - in their tooling, languages, and more. In fact, it’s likely what drew you to Vue in the first place. Start simple - then scale up as needed.&lt;/p&gt;

&lt;p&gt;So, if you’d prefer to use JavaScript instead of TypeScript, you can. After generating an Ionic Vue app (see above), follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Remove TypeScript dependencies:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm uninstall &lt;span class="nt"&gt;--save&lt;/span&gt; typescript @types/jest @typescript-eslint/eslint-plugin @typescript-eslint/parser @vue/cli-plugin-typescript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Change all &lt;code&gt;.ts&lt;/code&gt; files to &lt;code&gt;.js&lt;/code&gt;. In a blank Ionic Vue app, this should only be &lt;code&gt;router/index.ts&lt;/code&gt; and &lt;code&gt;main.ts&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove &lt;code&gt;@vue/typescript/recommended&lt;/code&gt; and &lt;code&gt;@typescript-eslint/no-explicit-any&lt;/code&gt;: 'off', from &lt;code&gt;.eslintrc.js&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove &lt;code&gt;Array&amp;lt;RouteRecordRaw&amp;gt;&lt;/code&gt; from &lt;code&gt;router/index.js&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Truly native experiences with Vue 📱
&lt;/h3&gt;

&lt;p&gt;Vue does not natively support mobile app development, but fortunately, you can pair Ionic Vue with &lt;a href="https://capacitorjs.com" rel="noopener noreferrer"&gt;Capacitor&lt;/a&gt;. Using Ionic’s official cross-platform native runtime, you can deploy your apps as progressive web apps &lt;em&gt;and&lt;/em&gt; iOS/Android apps - all from the same codebase.&lt;/p&gt;

&lt;p&gt;Here’s an example using two Capacitor APIs, the &lt;a href="https://capacitorjs.com/docs/apis/camera" rel="noopener noreferrer"&gt;Camera&lt;/a&gt; and &lt;a href="https://capacitorjs.com/docs/apis/filesystem" rel="noopener noreferrer"&gt;Filesystem&lt;/a&gt;. After opening the camera on the mobile device, the user can take a new photo, then save it to device storage.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;takePhoto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cameraPhoto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Camera&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getPhoto&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;resultType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CameraResultType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CameraSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Camera&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;base64Data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;convertPhotoToBase64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cameraPhoto&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;savedFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Filesystem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFile&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myphoto.jpg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;base64Data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FilesystemDirectory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that there’s no mention of “web”, “iOS”, or “Android” in the code. That’s because Capacitor automatically detects the platform the app is running on, and calls the appropriate native layer code. With Core APIs like these, coupled with full access to native SDKs, Capacitor empowers you to build truly native mobile apps.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next? 🛣
&lt;/h2&gt;

&lt;p&gt;For a more in-depth look at Ionic Vue, we recommend checking our &lt;a href="https://ionicframework.com/docs/vue/quickstart" rel="noopener noreferrer"&gt;Quickstart Guide&lt;/a&gt;. For a more hands-on experience, take a look at our &lt;a href="https://ionicframework.com/docs/vue/your-first-app" rel="noopener noreferrer"&gt;Build Your First App Guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While the release of Ionic Vue is an important milestone for Ionic Framework, there is always more to do. We plan on releasing complete Server Side Rendering (SSR) support for Ionic Vue in the future. Keep an eye out for a blog post on how you can get started with that!&lt;/p&gt;

&lt;p&gt;In terms of general Ionic Framework development, we have a lot of exciting things planned, so stay tuned. Also, let us know where you would like to see Ionic Framework go next by tweeting at us &lt;a href="https://twitter.com/ionicframework" rel="noopener noreferrer"&gt;@ionicframework&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Thank You 💙
&lt;/h2&gt;

&lt;p&gt;I want to give a &lt;strong&gt;huge&lt;/strong&gt; thank you to all the community members who helped test the Ionic Vue beta and provide feedback; this project would not have been possible without your support. Special thanks to the folks over at &lt;a href="https://moduscreate.com/" rel="noopener noreferrer"&gt;Modus Create&lt;/a&gt; and specifically &lt;a href="https://github.com/michaeltintiuc" rel="noopener noreferrer"&gt;Michael Tintiuc&lt;/a&gt; for helping us get Ionic Vue to where it is today.&lt;/p&gt;

&lt;p&gt;We are thrilled about Ionic Vue and are excited to welcome all Vue developers to the Ionic community. We are so glad you are here and cannot wait to see what you build!&lt;/p&gt;

</description>
      <category>ionic</category>
      <category>vue</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How to Confirm Leaving a Page in Ionic React with React Router</title>
      <dc:creator>Ely Lucas</dc:creator>
      <pubDate>Fri, 09 Oct 2020 14:00:42 +0000</pubDate>
      <link>https://dev.to/ionic/how-to-confirm-leaving-a-page-in-ionic-react-with-react-router-p55</link>
      <guid>https://dev.to/ionic/how-to-confirm-leaving-a-page-in-ionic-react-with-react-router-p55</guid>
      <description>&lt;p&gt;Have you ever been in the middle of an important task on a page, like filling out a form, and accidentally left and lost all your work? That bites! &lt;/p&gt;

&lt;p&gt;And it's a bad experience for your users, especially on mobile.&lt;/p&gt;

&lt;p&gt;A typical technique is to confirm with the user if they do want to leave the page with a confirmation dialog. In this post, I'll show you how to do so in an Ionic React application, and how you can customize the confirmation UI to fit your particular app. Let's go!&lt;/p&gt;

&lt;h2&gt;
  
  
  Using React Router's Prompt Component
&lt;/h2&gt;

&lt;p&gt;An Ionic React application uses &lt;a href="https://reactrouter.com/" rel="noopener noreferrer"&gt;React Router&lt;/a&gt; for all of its navigation, and, fortunately, React Router has good support for prompting the user on navigation with their &lt;a href="https://reactrouter.com/web/api/Prompt" rel="noopener noreferrer"&gt;&lt;code&gt;Prompt&lt;/code&gt;&lt;/a&gt; component. With Prompt, a confirmation box pops up asking the user if they want to leave the page. If they click yes, the navigation takes place, and if they click no, they are left on the current page.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Prompt&lt;/code&gt; component takes two props, a &lt;code&gt;message&lt;/code&gt; to display, and a &lt;code&gt;when&lt;/code&gt; boolean to activate it.&lt;/p&gt;

&lt;p&gt;Here is a simple IonPage with a form that utilizes the Prompt component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Tab1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setText&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useIonViewWillLeave&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;IonPage&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;IonHeader&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;IonToolbar&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;IonTitle&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Tab 1&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;IonTitle&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;IonToolbar&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;IonHeader&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;IonContent&lt;/span&gt; &lt;span class="na"&gt;fullscreen&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;IonInput&lt;/span&gt;
          &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Name"&lt;/span&gt;
          &lt;span class="na"&gt;onIonChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;setText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;IonInput&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;IonButton&lt;/span&gt;
          &lt;span class="na"&gt;expand&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"block"&lt;/span&gt;
          &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;setText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          Submit
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;IonButton&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Prompt&lt;/span&gt;
          &lt;span class="na"&gt;when&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"You have unsaved changes, are you sure you want to leave?"&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;IonContent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;IonPage&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Prompt is imported from 'react-router'&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To determine if the form is "dirty" (if the form has been modified), we check to see if the &lt;code&gt;IonInput&lt;/code&gt; has a value or not. This is a simple method, and you will probably need to expand on the concept in your app. Many form libraries provide a way to determine if the form has been modified as well.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;useIonViewWillLeave&lt;/code&gt; hook, when a user leaves the page, we set the value of text back to a blank string to "reset" the form. This keeps the prompt from showing on other pages.&lt;/p&gt;

&lt;p&gt;Now, if we try to leave the form, by say, accidentally tapping one of the other tab buttons, we get a nice confirmation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcsppmi5rsxrk2reu2udf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcsppmi5rsxrk2reu2udf.jpg" alt="Image of form with standard browser confirm dialog"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is fairly functional as is. The confirm dialog on mobile devices looks decent, but if you want to customize the UI, we will dive into that next.&lt;/p&gt;

&lt;h2&gt;
  
  
  Customizing the Confirm UI
&lt;/h2&gt;

&lt;p&gt;Instead of showing the built-in confirm dialog that comes with the browser, you might want to display something a bit more custom to match the look and feel of your app. To change it up, we will use an &lt;a href="https://ionicframework.com/docs/api/alert" rel="noopener noreferrer"&gt;&lt;code&gt;IonAlert&lt;/code&gt;&lt;/a&gt; with custom buttons for the confirmation.&lt;/p&gt;

&lt;p&gt;React Router provides a way to tie into the process by passing in a &lt;code&gt;getUserConfirmation&lt;/code&gt; prop when setting up the router. In an Ionic app, we use &lt;code&gt;IonReactRouter&lt;/code&gt; and we can pass this prop here and the router will, in turn, pass the prop back down to the underlying &lt;code&gt;ReactRouter&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This prop excepts a function that gets passed in the message to display, as well as a callback. The callback takes a boolean parameter to indicate if the route navigation should happen or not. We'll add it to the main &lt;code&gt;App.tsx&lt;/code&gt; page, where the routing is set up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;IonReactRouter&lt;/span&gt;
  &lt;span class="na"&gt;getUserConfirmation&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When &lt;code&gt;getUserConfirmation&lt;/code&gt; is called, we want to display an &lt;code&gt;IonAlert&lt;/code&gt; overlay with the message that was passed in. We will use a state variable to store the message. Also, we utilize a ref object to hold a reference to the callback that will be used in the alert:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;leaveConfirmMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLeaveConfirmMessage&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;confirmCallback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And to set them in the &lt;code&gt;getUserConfirmation&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;IonReactRouter&lt;/span&gt;
  &lt;span class="na"&gt;getUserConfirmation&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setLeaveConfirmMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;confirmCallback&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we add the &lt;code&gt;IonAlert&lt;/code&gt; towards the bottom of the page, but before the closing &lt;code&gt;&amp;lt;/IonReactRouter&amp;gt;&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;IonAlert&lt;/span&gt;
  &lt;span class="na"&gt;isOpen&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;leaveConfirmMessage&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;leaveConfirmMessage&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;buttons&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;No&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;confirmCallback&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;confirmCallback&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;current&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Yes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;confirmCallback&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;confirmCallback&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;current&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;onDidDismiss&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setLeaveConfirmMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To determine if the alert is shown, we check if the confirm message has a value, and then set the message back to undefined when the alert is dismissed. In the buttons, we use the ref we set up to invoke the callback function, passing true when the user clicks "Yes", and false when "No" is clicked.&lt;/p&gt;

&lt;p&gt;And that's it! We use the &lt;code&gt;Prompt&lt;/code&gt; component as we did before in any page we want to use this custom UI. No changes are needed in our form page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fblpqtn6qyb20kkyndyoy.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fblpqtn6qyb20kkyndyoy.jpg" alt="Image of form with custom dialog using IonAlert"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the Browsers &lt;code&gt;beforeUnload&lt;/code&gt; Event
&lt;/h2&gt;

&lt;p&gt;One last thing we need to cover, which is what happens when the user tries to move away from the page outside of our app, like via the back button or changing the URL manually?&lt;/p&gt;

&lt;p&gt;We can use the browser's &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event" rel="noopener noreferrer"&gt;&lt;code&gt;beforeUnload&lt;/code&gt;&lt;/a&gt; event for this, though it is not customizable, browser support is limited, and it requires a bit more code. However, setting it up will give our users whose browsers support it extra protection if they, say, accidentally refresh their page.&lt;/p&gt;

&lt;p&gt;Back in the page with the form, we will add a &lt;code&gt;useEffect&lt;/code&gt; hook to monitor the &lt;code&gt;text&lt;/code&gt; state. We set the &lt;code&gt;onbeforeunload&lt;/code&gt; method on the window object to a function that returns &lt;code&gt;true&lt;/code&gt; when the text has a value, and when the effect changes, set it &lt;code&gt;null&lt;/code&gt; to turn it back off:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onbeforeunload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onbeforeunload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This could also be abstracted into its own component or hook for reuse.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Adding some safeguards to prevent your users from accidentally leaving a page while they are performing an important task is, thankfully, pretty straight-forward in an Ionic React app thanks to the built-in support in React Router. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/elylucas/ionic-react-leave-page-confirm" rel="noopener noreferrer"&gt;I put together a demo app you can take a look at&lt;/a&gt;, feel free to check it out. Also, hit me up on twitter &lt;a class="mentioned-user" href="https://dev.to/elylucas"&gt;@elylucas&lt;/a&gt; or in the comments below if you have any questions.&lt;/p&gt;

&lt;p&gt;Happy Coding!&lt;/p&gt;

</description>
      <category>ionic</category>
      <category>react</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Pullstate - Simple hooks-based state management for React</title>
      <dc:creator>Max Lynch</dc:creator>
      <pubDate>Mon, 21 Sep 2020 22:25:53 +0000</pubDate>
      <link>https://dev.to/ionic/pullstate-simple-hooks-based-state-management-for-react-5bc4</link>
      <guid>https://dev.to/ionic/pullstate-simple-hooks-based-state-management-for-react-5bc4</guid>
      <description>&lt;p&gt;State management is one of the most important pieces of an app, and there are a ton of choices for those in the React ecosystem.&lt;/p&gt;

&lt;p&gt;In particular, developers building iOS and Android mobile apps with React using &lt;a href="https://capacitorjs.com/"&gt;Capacitor&lt;/a&gt; and &lt;a href="http://ionicframework.com/react"&gt;Ionic React&lt;/a&gt; often ask us for state management recommendations. Of course, there's Redux, which I remain a &lt;a href="https://medium.com/@maxlynch/redux-is-the-pivotal-frontend-innovation-a406736552cb"&gt;major fan of&lt;/a&gt;, but also much simpler state management approaches like MobX and &lt;a href="https://ionicframework.com/blog/a-state-management-pattern-for-ionic-react-with-react-hooks/"&gt;rolling your own using the Context API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I've spent a lot of time using Redux and also the bespoke approach with the Context API. Yet, I wasn't satisfied. I wanted to find something that was simple but high performance, and had native integration with Hooks and Function components which I now use exclusively in React (sorry, never want to write the word &lt;code&gt;class&lt;/code&gt; ever again 😆).&lt;/p&gt;

&lt;p&gt;That's when I stumbled on &lt;a href="https://lostpebble.github.io/pullstate/"&gt;Pullstate&lt;/a&gt;. Pullstate is a small, relatively unknown library (just 300 stars at the time of this writing), but I expect it will become much more popular in time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exploring Pullstate
&lt;/h2&gt;

&lt;p&gt;Pullstate provides a simple Store object that is registered globally, and provides hooks for accessing data from that store in a component:&lt;/p&gt;

&lt;p&gt;store.ts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;StoreType&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;currentProject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Project&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Store&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;StoreType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
 &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;currentProject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;MyStore&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, in your component, simply use the &lt;code&gt;useState&lt;/code&gt; method provided on the store to select data from the store:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UserProfile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;MyStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Modifying state
&lt;/h2&gt;

&lt;p&gt;To update state in the store, use the &lt;code&gt;update&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;setUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;MyStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;update&lt;/code&gt; function works by mutating a Draft of the state. That draft is then processed to produce a new state.&lt;/p&gt;

&lt;p&gt;Usually, a state mutation would raise a red flag, but the magic of Pullstate comes from a really interesting project called &lt;a href="https://github.com/immerjs/immer"&gt;Immer&lt;/a&gt;. Immer essentially proxies an object and then turns mutations on that object into a new object (in my limited experience with it). Sort of how the vdom does diffing to figure out a new DOM tree.&lt;/p&gt;

&lt;p&gt;This is incredibly powerful and simple, but does have a few gotcha's. First, reference comparisons on objects in the &lt;code&gt;s&lt;/code&gt; value above will fail, because they are actually &lt;code&gt;Proxy&lt;/code&gt; objects. That means doing something like this won't work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;MyStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;project&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;projects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;newProject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead, use the second argument, &lt;code&gt;o&lt;/code&gt; above, which contains the un-proxied original state. Another gotcha is making sure not to return anything from the &lt;code&gt;update&lt;/code&gt; function.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next steps
&lt;/h2&gt;

&lt;p&gt;After having used Pullstate, I will have a hard time not recommending it to all &lt;a href="https://ionicframework.com/react"&gt;Ionic React&lt;/a&gt; developers, and those using &lt;a href="https://capacitorjs.com/"&gt;Capacitor&lt;/a&gt; with other React UI libraries.&lt;/p&gt;

&lt;p&gt;I think Pullstate is a great middle ground between being simple for small projects, but clearly capable of scaling to much more complicated projects. For larger projects multiple stores can be created in parallel, for a sort of redux reducer-inspired organization.&lt;/p&gt;

&lt;p&gt;Pullstate also comes with some convenience helpers for &lt;a href="https://lostpebble.github.io/pullstate/docs/async-actions-introduction"&gt;async actions&lt;/a&gt; to cut down on async state boilerplate (such as handling success and failure states), though I have not used those extensively yet.&lt;/p&gt;

&lt;p&gt;Next on my list is exploring how this might work with something like &lt;a href="https://github.com/reduxjs/reselect"&gt;reselect&lt;/a&gt; for building reusable, memoized selectors.&lt;/p&gt;

&lt;p&gt;What do you think? Have you used Pullstate? Please share in the comments!&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>ionic</category>
    </item>
  </channel>
</rss>
