<?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: sina safari</title>
    <description>The latest articles on DEV Community by sina safari (@sinasafari).</description>
    <link>https://dev.to/sinasafari</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F916298%2F65baf804-d650-4647-8501-403eaae95d85.jpeg</url>
      <title>DEV Community: sina safari</title>
      <link>https://dev.to/sinasafari</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sinasafari"/>
    <language>en</language>
    <item>
      <title>Upload file in Sveltekit</title>
      <dc:creator>sina safari</dc:creator>
      <pubDate>Sat, 14 Jan 2023 13:08:09 +0000</pubDate>
      <link>https://dev.to/sinasafari/upload-file-in-sveltekit-2jnl</link>
      <guid>https://dev.to/sinasafari/upload-file-in-sveltekit-2jnl</guid>
      <description>&lt;p&gt;sveltekit is trending nowadays and I believe it totally deserves it. I tried it for one of my side projects and enjoyed it.&lt;/p&gt;

&lt;p&gt;sveltekit is a fullstack meta-framework for sveltejs that can handle almost everything we need for developing a web application. one of these features is file uploading and storing it to file system.&lt;br&gt;
for uploading images (or other types of files) in sveltekit, we have 2 options. form actions, and API routes.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;em&gt;template&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;in &lt;code&gt;+page.svelte&lt;/code&gt; we can create a form with &lt;code&gt;multipart/form-data&lt;/code&gt; as its enctype. this form submits to an action handler (that we are to implement in a moment):&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;form&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"?/avatar"&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"post"&lt;/span&gt; &lt;span class="na"&gt;enctype=&lt;/span&gt;&lt;span class="s"&gt;"multipart/form-data"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"file"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"avatar"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"avatar"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;upload&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;em&gt;Action Handler&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;as the sveltekit documentation says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;actions allow you to POST data to the server using the &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; element.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;basically, they are functions that run on the server and are specifically designed for accepting form actions. you can read more about them in &lt;a href="https://kit.svelte.dev/docs/form-actions" rel="noopener noreferrer"&gt;sveltekit documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;we have to create an action handler in &lt;code&gt;+page.server.ts&lt;/code&gt;. this file can be used for providing page initial data (by exporting a function named &lt;code&gt;load&lt;/code&gt;) and defining form action handlers.&lt;br&gt;
note that as specified in &lt;code&gt;&amp;lt;form /&amp;gt;&lt;/code&gt; tag, the action name should be &lt;code&gt;avatar&lt;/code&gt;.&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="nx"&gt;fs&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;fs/promises&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;path&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;path&lt;/span&gt;&lt;span class="dl"&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;redirect&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;@sveltejs/kit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&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;PageLoad&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Actions&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;./$types&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Actions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;url&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;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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromEntries&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;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;formData&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;filePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&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="nf"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;static&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;avatars&lt;/span&gt;&lt;span class="dl"&gt;'&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="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomUUID&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="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;avatar&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Blob&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="nf"&gt;split&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="mi"&gt;1&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&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="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await &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="nx"&gt;avatar&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Blob&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;arrayBuffer&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;

      &lt;span class="c1"&gt;// TODO: store the file path in database for further references.&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;303&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&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;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nf"&gt;fail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;err&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;that's it! now the uploaded file will be stored in the static folder and it's accessible like other static assets.&lt;/p&gt;

&lt;p&gt;also, I used &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API" rel="noopener noreferrer"&gt;crypto module&lt;/a&gt; for naming files in the file system instead of the original file name, for having the same naming format for all files and removing long file names.&lt;/p&gt;

&lt;p&gt;note that this code is not completed logic. the path of the uploaded file should be stored in a persisted storage or database for further usage. also, errors should be handled properly.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;em&gt;API routes&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;the same functionality can be applied as an API route as well. forms should be submitted using javascript in this way. also if you have multiple clients besides your client-side sveltekit app (like a react-native mobile app) this approach is the one should choose.&lt;/p&gt;

&lt;p&gt;we can define API route endpoints in &lt;code&gt;+server.ts&lt;/code&gt;. for specifying handlers for different HTTP methods (&lt;code&gt;GET&lt;/code&gt;, &lt;code&gt;POST&lt;/code&gt;, etc.) we can declare a function with the name of the HTTP verb. here we want a handler for&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="nx"&gt;path&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;path&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;fs&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;fs/promises&lt;/span&gt;&lt;span class="dl"&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;fail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;redirect&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;@sveltejs/kit&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="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RequestHandler&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;./$types&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;POST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;url&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;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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromEntries&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;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;formData&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;filePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&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="nf"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;static&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;avatars&lt;/span&gt;&lt;span class="dl"&gt;"&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="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomUUID&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="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;avatar&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Blob&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="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&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="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await &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="nx"&gt;avatar&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Blob&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;arrayBuffer&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
            &lt;span class="c1"&gt;// TODO: store the file path in database for further references.&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&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="nx"&gt;filePath&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;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nf"&gt;fail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;err&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;satisfies&lt;/span&gt; &lt;span class="nx"&gt;RequestHandler&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that in API routes the response body should be generated with &lt;code&gt;Response&lt;/code&gt; object (which is global to typescript) so it's a little different from form actions.&lt;/p&gt;

&lt;p&gt;you can read more about the API routes in &lt;a href="https://kit.svelte.dev/docs/routing#server" rel="noopener noreferrer"&gt;sveltekit routing documentation&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;after all, if you need to have static file serving, you should change &lt;code&gt;vite.config.js&lt;/code&gt; in the root of the project a little:&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;sveltekit&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;@sveltejs/kit/vite&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;searchForWorkspaceRoot&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;vite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="cm"&gt;/** @type {import('vite').UserConfig} */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;sveltekit&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
    &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;allow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;searchForWorkspaceRoot&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="nf"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/static/avatars/&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="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/**/*.{test,spec}.{js,ts}&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;






&lt;p&gt;Although this method works fine for small apps, storing assets and serving them through static path is not considered a best practice. it's not about sveltekit limitations, using an object storage service like Amazon S3 or MinIO is preferred for larger applications.&lt;/p&gt;

&lt;p&gt;hope you find this post useful!&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>discuss</category>
    </item>
    <item>
      <title>How I go with react native in late 2022</title>
      <dc:creator>sina safari</dc:creator>
      <pubDate>Sun, 27 Nov 2022 12:25:12 +0000</pubDate>
      <link>https://dev.to/sinasafari/how-i-go-with-react-native-in-late-2022-44gp</link>
      <guid>https://dev.to/sinasafari/how-i-go-with-react-native-in-late-2022-44gp</guid>
      <description>&lt;p&gt;In the javascript world, there are more than a million tools and libraries for developing the smallest feature in your application.&lt;br&gt;
in the RN world, and in late 2022, I usually use these tools:&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Base project&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;although there are many templates in the community, I prefer the minimal and default &lt;code&gt;react-native init&lt;/code&gt; with base &lt;code&gt;react-native-template-typescript&lt;/code&gt; which is recommended in the official docs.&lt;br&gt;
the default template uses &lt;code&gt;flow&lt;/code&gt; as a javascript type system extender. but, typescript is the most reliable and safe programming language with large community support for&lt;br&gt;
developing large-scale apps. so, typescript is always my choice over pure javascript and other tools.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/infinitered/ignite" rel="noopener noreferrer"&gt;ignite&lt;/a&gt; is a fine template too. the template is preconfigured with &lt;code&gt;expo&lt;/code&gt; and &lt;code&gt;react-native-cli&lt;/code&gt;. but I don't agree with some of their decisions. for example, using &lt;code&gt;mobx&lt;/code&gt; and &lt;code&gt;apisause&lt;/code&gt;.&lt;br&gt;
but I always use their template to use config files, etc. the sample app is configured so well.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Networking&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;unless you are developing a calculator app or something like this, you will need some network access and API requests. in my opinion, &lt;a href="https://github.com/axios/axios" rel="noopener noreferrer"&gt;axios&lt;/a&gt; is the best option for networking in any js-based application. &lt;code&gt;axios&lt;/code&gt; is fully configurable, and it's easy to use compared to fetch API (which is the react-native default way).&lt;/p&gt;

&lt;p&gt;calling an API is not enough in most cases. caching (or keeping server-client data) and state management is important as well. although all of them can be handled completely manually, I prefer to use a 3rd-party package, which is well-tested and provides clean API.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;There are only two hard things in Computer Science: cache invalidation and naming things.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;-- Phil Karlton&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://github.com/tanstack/query" rel="noopener noreferrer"&gt;react-query&lt;/a&gt; helps us to handle server-client caching (btw, cache revalidation is one of the hardest problems in computer engineering), and also helps us write asynchronous code like it's synchronous. I mean we can get data from an external resource (eg. API call) without writing a single &lt;code&gt;try catch&lt;/code&gt; block, and without any manual state changing.&lt;/p&gt;

&lt;p&gt;another option is the &lt;code&gt;redux toolkit query&lt;/code&gt; which is fully compatible with redux, but like redux itself, it requires boilerplate code. I prefer &lt;code&gt;react-query&lt;/code&gt; for all the use cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Routing&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/react-navigation/react-navigation" rel="noopener noreferrer"&gt;react-navigation&lt;/a&gt; is the best option for 99.9% of cases (that 0.1% is when you need to integrate react native with native code).&lt;br&gt;
it provides different navigation strategies, like &lt;code&gt;stack&lt;/code&gt;, &lt;code&gt;drawer&lt;/code&gt;, &lt;code&gt;tab&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;another option is &lt;a href="https://github.com/wix/react-native-navigation" rel="noopener noreferrer"&gt;react-native-navigation&lt;/a&gt; which I haven't used yet but as the document says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is a popular alternative to React Navigation and may be a better fit for you if you are trying to integrate React Native into an existing large native app.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I'm curious about it and I intend to try it in my upcoming side projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;State management&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/reduxjs/redux-toolkit" rel="noopener noreferrer"&gt;redux-toolkit&lt;/a&gt; is the famous option for managing the global state in react-native. but most of the time, the project does not need a huge global state. the application is divided into&lt;br&gt;
smaller modules that have their state. also, &lt;code&gt;redux-toolkit&lt;/code&gt; still requires more boilerplate code in comparison to its rivals.&lt;br&gt;
I had similar issues and recently I tried &lt;a href="https://github.com/pmndrs/zustand" rel="noopener noreferrer"&gt;zustand&lt;/a&gt; on my react-native project and I enjoyed it. I will choose it for my next project as well.&lt;br&gt;
&lt;code&gt;zustand&lt;/code&gt; is so small and does not need a provider or wrapper component. so it can be local to a module.&lt;/p&gt;

&lt;p&gt;all server-client cache is handled by &lt;code&gt;react-qeury&lt;/code&gt;, so only client-side states will be handled by the state manager tool (and in most cases, it's not an async action).&lt;br&gt;
so a small library like &lt;code&gt;zustand&lt;/code&gt; looks better in my opinion.&lt;/p&gt;

&lt;p&gt;there's another option that is not as practical as &lt;code&gt;redux&lt;/code&gt; and &lt;code&gt;zustand&lt;/code&gt;, but I like it. &lt;code&gt;BLOC&lt;/code&gt; is a state management pattern (not necessarily a global state) that is&lt;br&gt;
so popular in the flutter community. this pattern is based on reactive programming and streams. Felix Angelov made &lt;a href="https://github.com/felangel/bloc.js" rel="noopener noreferrer"&gt;bloc.js&lt;/a&gt; that help us to implement this pattern.&lt;br&gt;
as I said, it may not be a suitable option for enterprise-level react-native applications, but definately it's a cool library.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Database&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;for most applications, &lt;a href="https://github.com/react-native-async-storage/async-storage" rel="noopener noreferrer"&gt;AsyncStorage&lt;/a&gt; works fine. also, you can use it with &lt;a href="https://github.com/rt2zz/redux-persist" rel="noopener noreferrer"&gt;redux-persist&lt;/a&gt; or persist middleware of &lt;code&gt;zustand&lt;/code&gt;.&lt;br&gt;
in this way, you won't even need to touch the &lt;code&gt;AsyncStorage&lt;/code&gt;. my first choice as a database (or just a persistor tool) is &lt;code&gt;zustand&lt;/code&gt; and &lt;code&gt;AsyncStorage&lt;/code&gt;. this combination can solve storage issues most of the time.&lt;/p&gt;

&lt;p&gt;There's another option that I like to use in my next project. &lt;a href="https://nozbe.github.io/WatermelonDB/Installation.html" rel="noopener noreferrer"&gt;WatermelonDB&lt;/a&gt; is a relational database that is powered by SQLite but is observable.&lt;br&gt;
also, &lt;code&gt;WatermelonDB&lt;/code&gt; can be synchronized with a remote database which can be useful in most cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;UI&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;you may need nothing but react-native's &lt;code&gt;StyleSheet&lt;/code&gt; module to completely style an application, but it is not easy and it may result in a log of repetitive style props.&lt;/p&gt;

&lt;p&gt;UI libraries and frameworks try to solve this repetition issue by creating predefined components. unlike web UI libraries (like material UI, or mantine), react-native UI libraries are not full of ready-to-use components. most of them are incomplete in comparison to web UI libraries. but I think &lt;a href="https://github.com/GeekyAnts/NativeBase" rel="noopener noreferrer"&gt;native-base&lt;/a&gt; is the best option among them. it provides theming options and a lot of reusable and configurable components. &lt;code&gt;native-base&lt;/code&gt; overrides all &lt;code&gt;react-native&lt;/code&gt; default components (like &lt;code&gt;View&lt;/code&gt;, &lt;code&gt;Flatlist&lt;/code&gt;, etc) and let us give styles attributes as props to those components and elements. I love this feature. &lt;code&gt;native-base&lt;/code&gt; is my number one option for my react-native projects.&lt;/p&gt;

&lt;p&gt;There's another option that I haven't used yet, but I think that it's a great option. &lt;a href="https://github.com/marklawlor/nativewind" rel="noopener noreferrer"&gt;nativewind&lt;/a&gt; brings &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;tailwindcss&lt;/a&gt; to react-native. some other libraries try to do the same, but I think &lt;code&gt;nativewind&lt;/code&gt; looks better than the others.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Animation&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;react-native provides an &lt;code&gt;Animated&lt;/code&gt; API for developing animated UI components. but it's not the optimal way of animating elements. this is mostly related to the architecture of react-native and communication of the js thread and native thread.&lt;/p&gt;

&lt;p&gt;the solution is &lt;a href="https://github.com/software-mansion/react-native-reanimated" rel="noopener noreferrer"&gt;react-native-reanimated&lt;/a&gt;. &lt;code&gt;reanimated&lt;/code&gt; helps us to create smooth and performant animations with minimal setup, with a lot of helpers, and is relatively easy to use. another useful library for handling gesture animations is &lt;a href="https://github.com/software-mansion/react-native-gesture-handler" rel="noopener noreferrer"&gt;react-native-gesture-handler&lt;/a&gt; which is defined as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;native-driven gesture management APIs for building the best possible touch-based experiences in React Native.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;react-native-gesture-handler website&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;these two libraries are dependencies for some other libraries as well. for example, the &lt;code&gt;react-navigation&lt;/code&gt; drawer requires this library to function.&lt;/p&gt;

&lt;p&gt;a high-level alternative to &lt;code&gt;react-native-reanimated&lt;/code&gt; is &lt;a href="https://github.com/nandorojo/moti" rel="noopener noreferrer"&gt;moti&lt;/a&gt;. &lt;code&gt;moti&lt;/code&gt; uses &lt;code&gt;reanimated&lt;/code&gt; as its dependency and provides a high-level API for animations in react native. it looks like &lt;code&gt;framer-motion&lt;/code&gt; on the web and provides similar APIs.&lt;/p&gt;

&lt;p&gt;another library that I want to try is &lt;a href="https://github.com/Shopify/react-native-skia" rel="noopener noreferrer"&gt;react-native-skia&lt;/a&gt; which is not completely related to animations but I think this is the best section for mentioning it. it's a 2D graphical rendering engine that is popular for being used as a renderer engine in flutter. as the website says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;React Native Skia brings the Skia Graphics Library to React Native. Skia serves as the graphics engine for Google Chrome and Chrome OS, Android, Flutter, Mozilla Firefox, Firefox OS, and many other products.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;although using this library will increase bundle size up to 6MB in mobile apps, in some special cases might be a good option.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Development and collaboration&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;my version control tool is &lt;code&gt;git&lt;/code&gt; and &lt;code&gt;github&lt;/code&gt; is the platform that my source code lives on. there are some other tools like &lt;a href="https://github.com/eslint/eslint" rel="noopener noreferrer"&gt;eslint&lt;/a&gt; (for linting and setting some rules),&lt;br&gt;
&lt;a href="https://github.com/prettier/prettier" rel="noopener noreferrer"&gt;prettier&lt;/a&gt; (for having the same code style between different editors and IDEs), &lt;a href="https://github.com/typicode/husky" rel="noopener noreferrer"&gt;husky&lt;/a&gt; (for managing git hooks)&lt;/p&gt;

&lt;p&gt;having a code review and analysis tool in CI/CD pipeline can help developers to keep their code clean. some examples of these tools are &lt;a href="https://www.sonarqube.org/" rel="noopener noreferrer"&gt;sonarqube&lt;/a&gt; and &lt;a href="https://embold.io/" rel="noopener noreferrer"&gt;embold&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Testing&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;There's nothing better than &lt;a href="https://github.com/facebook/jest" rel="noopener noreferrer"&gt;jest&lt;/a&gt; and &lt;a href="https://testing-library.com/docs/react-native-testing-library/intro/" rel="noopener noreferrer"&gt;testing-library/react-native&lt;/a&gt; in react-native.&lt;br&gt;
these tools are suitable for unit and integration tests and they have great community support, utils, and helper functions.&lt;/p&gt;

&lt;p&gt;I haven't used it yet, but it seems &lt;a href="https://wix.github.io/Detox/" rel="noopener noreferrer"&gt;detox&lt;/a&gt; is a fine e2e testing tool for react native. something like &lt;a href="https://www.cypress.io/" rel="noopener noreferrer"&gt;cypress&lt;/a&gt; in the web.&lt;br&gt;
I think it's a little hard to configure, but in the end, it's really helpful.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;App build and versioning&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;for versioning builds, &lt;a href="https://github.com/stovmascript/react-native-version" rel="noopener noreferrer"&gt;react-native-version&lt;/a&gt; beside &lt;a href="https://github.com/sindresorhus/np" rel="noopener noreferrer"&gt;np&lt;/a&gt;, is pretty helpful.&lt;/p&gt;

&lt;p&gt;since my remote code repository is github, the best way to handle CI/CD pipeline is &lt;a href="https://github.com/features/actions" rel="noopener noreferrer"&gt;github actions&lt;/a&gt;. using this tool (or any other tool like &lt;a href="https://docs.gitlab.com/ee/ci/" rel="noopener noreferrer"&gt;gitlab-ci&lt;/a&gt;, &lt;a href="https://circleci.com/" rel="noopener noreferrer"&gt;circleci&lt;/a&gt;, etc),&lt;br&gt;
you can automate linting, testing, building, and publishing apps. &lt;code&gt;github actions&lt;/code&gt; has great community support. its best feature is that it's free.&lt;/p&gt;

&lt;p&gt;in my future projects, I want to try &lt;a href="https://appcenter.ms/" rel="noopener noreferrer"&gt;ms appcenter&lt;/a&gt; and &lt;a href="https://fastlane.tools/" rel="noopener noreferrer"&gt;fastlane&lt;/a&gt; as well. specifically &lt;code&gt;appcenter&lt;/code&gt; looks pretty useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Native features&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;native features like the Camera, Microphone, etc, are not necessary for all applications. but if they are likely to be used in one way or another. I used these libraries and they are pretty well-designed:&lt;/p&gt;

&lt;h3&gt;
  
  
  Camera
&lt;/h3&gt;

&lt;p&gt;for many years, &lt;a href="https://github.com/react-native-camera/react-native-camera/tree/master" rel="noopener noreferrer"&gt;react-native-camera&lt;/a&gt; was a good option for using the camera in react-native but now it's deprecated. a good option is &lt;a href="https://github.com/mrousavy/react-native-vision-camera" rel="noopener noreferrer"&gt;react-native-camera-vision&lt;/a&gt; which includes a set of well-designed API. also this library is more optimized than &lt;code&gt;react-native-camera&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Map
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/react-native-maps/react-native-maps" rel="noopener noreferrer"&gt;react-native-maps&lt;/a&gt; is the best option for handling location and maps in react native. you can use &lt;code&gt;openstreet&lt;/code&gt;, &lt;code&gt;google maps&lt;/code&gt;, &lt;code&gt;apple maps&lt;/code&gt;, or any other tile overlay. also, it provides some good examples in its repository which covers most of the use cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Biometrics and Keychain
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/SelfLender/react-native-biometrics" rel="noopener noreferrer"&gt;react-native-biometrics&lt;/a&gt; helps us to access functionalities like FaceID, TouchID, or any other biometric features that are available in the device. &lt;code&gt;react-native-biometrics&lt;/code&gt; uses the device Keystore for biometric authentication. it's helpful when you develop an application that is security intensive.&lt;/p&gt;

&lt;p&gt;by the way, if you want to access the native device keychain, &lt;a href="https://github.com/oblador/react-native-keychain" rel="noopener noreferrer"&gt;react-native-keychain&lt;/a&gt; is the right tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;these are some tools that I used in my previous projects or I intend to use in the future. but there are a lot of useful packages and libraries that I don't know, and&lt;br&gt;
they may provide even better solutions than the above ones. in my opinion, there's not a single best solution for a problem (specifically in javascript), and trying new tools, libraries, and approaches, always helped to think better about coding and finding solutions.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I hope you found this text useful!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
    </item>
  </channel>
</rss>
