<?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: I.G</title>
    <description>The latest articles on DEV Community by I.G (@igfreetech).</description>
    <link>https://dev.to/igfreetech</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%2F1168963%2F6f503b1b-09f4-46db-a9d2-c770160402b4.png</url>
      <title>DEV Community: I.G</title>
      <link>https://dev.to/igfreetech</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/igfreetech"/>
    <language>en</language>
    <item>
      <title>How to rename the base branch of your opened PR in GitHub</title>
      <dc:creator>I.G</dc:creator>
      <pubDate>Fri, 17 Nov 2023 17:50:57 +0000</pubDate>
      <link>https://dev.to/igfreetech/how-to-rename-the-base-branch-of-your-opened-pr-in-github-2po6</link>
      <guid>https://dev.to/igfreetech/how-to-rename-the-base-branch-of-your-opened-pr-in-github-2po6</guid>
      <description>&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;All you have to do is rename the branch in GitHub.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open your repository's branches page (/{your_user_id}/{your_repository_name}/branches) and rename the branch.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then, all PRs that had the branch as a base branch automatically are updated and the base branch is also changed to the renamed one.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;※ But, the PR that had the branch as a head branch doesn't be updated automatically. So, you need to re-create a new pull request once more.&lt;/p&gt;

&lt;p&gt;cf. &lt;a href="https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-branches-in-your-repository/renaming-a-branch"&gt;https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-branches-in-your-repository/renaming-a-branch&lt;/a&gt;&lt;/p&gt;

</description>
      <category>github</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to update a value instantaneously instead of asynchronously in React</title>
      <dc:creator>I.G</dc:creator>
      <pubDate>Wed, 15 Nov 2023 19:49:54 +0000</pubDate>
      <link>https://dev.to/igfreetech/how-to-update-a-value-instantaneously-instead-of-asynchronously-4p9f</link>
      <guid>https://dev.to/igfreetech/how-to-update-a-value-instantaneously-instead-of-asynchronously-4p9f</guid>
      <description>&lt;h1&gt;
  
  
  Overview
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;useState&lt;/code&gt; doesn't update a value instantaneously, so that value will be as it was even if it's accessed soon after &lt;code&gt;useState&lt;/code&gt; like below.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;cf. &lt;a href="https://ja.react.dev/reference/react/useState#usage"&gt;https://ja.react.dev/reference/react/useState#usage&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React handles the accumulated queues and updates state in bulk after all events executing in parallel completed being done.&lt;/li&gt;
&lt;li&gt;After that, components are re-rendered.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;cf. &lt;a href="https://ja.react.dev/learn/queueing-a-series-of-state-updates"&gt;https://ja.react.dev/learn/queueing-a-series-of-state-updates&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Counter&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&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="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 0&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="nt"&gt;div&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="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Count: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&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="nt"&gt;button&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="nx"&gt;handleClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Increment&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&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="nt"&gt;div&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;h1&gt;
  
  
  useRef
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;useRef&lt;/code&gt; as "escape hatch" to get the latest updated state when &lt;code&gt;setState&lt;/code&gt; is called in an asynchronous event(function).&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Gist
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;setState&lt;/code&gt; is an asynchronous function.&lt;/li&gt;
&lt;li&gt;The queue for updating the state is not captured by the lifecycle of the state in React when it is called in an asynchronous function. So the state is not updated then.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;cf. &lt;a href="https://crybabe.net/archives/12#toc1"&gt;https://crybabe.net/archives/12#toc1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;cf. &lt;a href="https://ja.react.dev/learn/referencing-values-with-refs#when-to-use-refs"&gt;https://ja.react.dev/learn/referencing-values-with-refs#when-to-use-refs&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Example&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&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="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&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;count2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount2&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="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&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;countRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&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;handleClick&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;setTimeout&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;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 0&lt;/span&gt;
      &lt;span class="nx"&gt;setCount2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 1&lt;/span&gt;
      &lt;span class="nx"&gt;countRef&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="mi"&gt;1&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;countRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 1&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&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;onSubmit&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 0&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="nx"&gt;count2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 0&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="nx"&gt;countRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 1&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="nt"&gt;div&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="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;countRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&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="nt"&gt;button&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="nx"&gt;handleClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Click me&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&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="nt"&gt;button&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="nx"&gt;onSubmit&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="nt"&gt;button&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="nt"&gt;div&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;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Example&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, you need to be careful about the point &lt;code&gt;useRef&lt;/code&gt; is independent of the React rendering cycle and so doesn't update DOM.&lt;/p&gt;

&lt;p&gt;In principle, it's important to design the overall logic in the component so that they can work even if &lt;code&gt;useState&lt;/code&gt; runs asynchronously.&lt;/p&gt;

&lt;h1&gt;
  
  
  Functional update
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Use a functional update way instead of the one to do directly if you wanna access an updated value soon after it's updated by &lt;code&gt;useState&lt;/code&gt; in the same event(function).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;cf. &lt;a href="https://zenn.dev/yuji6523/articles/react-usestate-function-update#%E7%B5%90%E5%B1%80%E3%81%AF%E5%B8%B8%E3%81%AB%E9%96%A2%E6%95%B0%E5%9E%8B%E3%82%A2%E3%83%83%E3%83%97%E3%83%87%E3%83%BC%E3%83%88%E3%82%92%E4%BD%BF%E3%81%88%E3%81%B0%E3%81%84%E3%81%84%E3%81%A6%E3%81%93%E3%81%A8%EF%BC%9F"&gt;Reference article(ja)&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;increaseDouble&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;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// not done&lt;/span&gt;
  &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// done&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="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 1&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;First &lt;code&gt;setCount(count + 1)&lt;/code&gt; is called. But &lt;code&gt;count&lt;/code&gt; is still 0 at this point due to the asynchronous update.&lt;/li&gt;
&lt;li&gt;Instantaneously, second &lt;code&gt;setCount(count + 1)&lt;/code&gt; is called. But &lt;code&gt;count&lt;/code&gt; is still 0 at this point too because 1st &lt;code&gt;setCount&lt;/code&gt; is not done yet.&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;So you can use a functional update to resolve that.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;cf. &lt;a href="https://ja.react.dev/reference/react/useState#updating-state-based-on-the-previous-state"&gt;https://ja.react.dev/reference/react/useState#updating-state-based-on-the-previous-state&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;increaseDouble&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;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// done&lt;/span&gt;
  &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// done&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="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 2&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;※ However seems there's no big difference between a functional update and a direct update for the most part except for the case like above.&lt;/p&gt;

</description>
      <category>react</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to exclude a file or folder when zipping a folder (on Mac)</title>
      <dc:creator>I.G</dc:creator>
      <pubDate>Thu, 19 Oct 2023 07:49:57 +0000</pubDate>
      <link>https://dev.to/igfreetech/how-to-exclude-a-file-or-folder-when-zipping-a-folder-on-mac-5f1n</link>
      <guid>https://dev.to/igfreetech/how-to-exclude-a-file-or-folder-when-zipping-a-folder-on-mac-5f1n</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# ex: zip -r app.zip ./app -x "*node_modules*"&lt;/span&gt;
&lt;span class="c"&gt;# ex2: zip -r app.zip ./zpp -x "*.pyc*"&lt;/span&gt;

zip &lt;span class="nt"&gt;-r&lt;/span&gt; &amp;lt;ZIP_FILE_NAME&amp;gt; &amp;lt;TARGET_FOLDER_PATH&amp;gt; &lt;span class="nt"&gt;-x&lt;/span&gt; &lt;span class="s2"&gt;"*&amp;lt;FILE_OR_FOLDER_PATTERN&amp;gt;*"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://blog.nekonium.com/zip/"&gt;Create a zip file excluding a specified file or folder(ja)&lt;/a&gt;&lt;/p&gt;

</description>
      <category>shell</category>
    </item>
    <item>
      <title>Safari automation test on your own iPhone with Selenium in 2023</title>
      <dc:creator>I.G</dc:creator>
      <pubDate>Wed, 18 Oct 2023 17:40:30 +0000</pubDate>
      <link>https://dev.to/igfreetech/safari-automation-test-on-your-own-iphone-with-selenium-57d6</link>
      <guid>https://dev.to/igfreetech/safari-automation-test-on-your-own-iphone-with-selenium-57d6</guid>
      <description>&lt;h1&gt;
  
  
  Prerequisites
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Settings &amp;gt; Safari &amp;gt; Details &amp;gt; Turn on "Remote automation" on your own iPhone.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Connect the iPhone with your Mac PC where Selenium codes run and then choose "Trust".&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://shawnlobo96.medium.com/running-a-website-automation-test-on-your-own-iphone-with-selenium-90907b51b27b"&gt;Running a website automation test on your own iPhone with Selenium&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Source code
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sleep&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;selenium&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;selenium.webdriver.safari.options&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Options&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;SafariOptions&lt;/span&gt;

&lt;span class="c1"&gt;# Use Options to set capabilities instead of DesiredCapabilities after Selenium 4
&lt;/span&gt;&lt;span class="n"&gt;safari_options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SafariOptions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;safari_options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_capability&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"platformName"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ios"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Safari&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;safari_options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://google.com"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>pyenv + pipenv (on Mac)</title>
      <dc:creator>I.G</dc:creator>
      <pubDate>Wed, 18 Oct 2023 17:06:04 +0000</pubDate>
      <link>https://dev.to/igfreetech/pyenv-pipenv-on-mac-24cj</link>
      <guid>https://dev.to/igfreetech/pyenv-pipenv-on-mac-24cj</guid>
      <description>&lt;h1&gt;
  
  
  Overview
&lt;/h1&gt;

&lt;p&gt;You can create a virtual environment of Python like nvm by installing &lt;strong&gt;pyenv&lt;/strong&gt; and &lt;strong&gt;pipenv&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;pyenv&lt;/strong&gt; is the version manager of Python(≒ &lt;u&gt;nvm&lt;/u&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;pipenv&lt;/strong&gt; is the library manager of Python.&lt;br&gt;
This manages installed libraries for each directories(projects) because the libraries installed via pipenv are installed in &lt;code&gt;~/.virtualenvs/&amp;lt;YOUR_DIRECTORY_NAME&amp;gt;-&amp;lt;UUID&amp;gt;&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;&amp;lt;YOUR_DIRECTORY_NAME&amp;gt;-&amp;lt;UUID&amp;gt;&lt;/code&gt; directory is automatically generated when pipenv installs a library in the directory.&lt;/p&gt;


&lt;h1&gt;
  
  
  Getting started
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://www.wakuwakubank.com/posts/255-python-pipenv-pyenv/"&gt;Steps (ja)&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Install pyenv
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;pyenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://github.com/pyenv/pyenv"&gt;pyenv | github.com&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Add the paths to $PATH to be able to activate pyenv command and manage python versions with it
&lt;/h2&gt;

&lt;p&gt;You need to add the following lines to .zprofile or .zshrc etc...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Add .pyenv/bin to $PATH to be able to run pyenv command anywhere&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.pyenv/bin:&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Add .pyenv/shims to $PATH to switch python versions with pyenv command&lt;/span&gt;
&lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;pyenv init -&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://medium.com/test-automation-university/how-to-manage-your-python-virtualenvs-with-pipenv-f1220ded702e"&gt;How to manage your python virtualenvs with Pipenv&lt;/a&gt;&lt;br&gt;
&lt;a href="https://pipenv.pypa.io/en/latest/installation/"&gt;Pipenv Installation&lt;/a&gt;&lt;br&gt;
&lt;a href="https://qiita.com/musatarosu/items/394603957ae41552718e#%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%97%E3%81%9F%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%81%AF%E3%81%A9%E3%81%93%E3%81%B8"&gt;Where does pipenv install a package (ja)&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Install a python version
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Show the list of version available for installation&lt;/span&gt;
pyenv &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;

&lt;span class="c"&gt;# Install the version&lt;/span&gt;
pyenv &lt;span class="nb"&gt;install&lt;/span&gt; &amp;lt;version&amp;gt; &lt;span class="c"&gt;# ex: pyenv install 3.12.0&lt;/span&gt;

&lt;span class="c"&gt;# Show the list of installed version&lt;/span&gt;
pyenv versions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  4. Set the python version in the local directory
&lt;/h2&gt;

&lt;p&gt;The python version is managed by &lt;code&gt;.python-version&lt;/code&gt; file created after the command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Set the version in local&lt;/span&gt;
pyenv &lt;span class="nb"&gt;local&lt;/span&gt; &amp;lt;version&amp;gt;

&lt;span class="c"&gt;# Show the current python version&lt;/span&gt;
pyenv version

&lt;span class="c"&gt;# Check whether python command is activated&lt;/span&gt;
python &lt;span class="nt"&gt;-V&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Install pipenv
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Pipfile&lt;/strong&gt; (≒ &lt;u&gt;package.json&lt;/u&gt;) is created after the installation command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;pipenv

&lt;span class="c"&gt;# Set the same python version as pyenv&lt;/span&gt;
pipenv &lt;span class="nt"&gt;--python&lt;/span&gt; &amp;lt;version&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/pypa/pipenv"&gt;pipenv | github.com&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Install a package and create a virtual environment
&lt;/h2&gt;

&lt;p&gt;When a package is installed for the first time in your current directory, &lt;code&gt;~/.virtualenvs/&amp;lt;YOUR_DIRECTORY_NAME&amp;gt;-&amp;lt;UUID&amp;gt;&lt;/code&gt; directory is created and then the package is installed there.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Add the package information to **Pipfile** and **Pipfile.lock** (be created if it doesn't exist)&lt;/span&gt;
pipenv &lt;span class="nb"&gt;install&lt;/span&gt; &amp;lt;PACKAGE_NAME&amp;gt;

&lt;span class="c"&gt;# Uninstall&lt;/span&gt;
pipenv uninstall &amp;lt;PACKAGE_NAME&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  7. Activate a virtual environment
&lt;/h2&gt;

&lt;p&gt;You need to enter the virtual environment created above to use the installed packages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Activate the local directory's environment&lt;/span&gt;
&lt;span class="c"&gt;# You can exit from it by entering `exit` if you want do&lt;/span&gt;
pipenv shell

&lt;span class="c"&gt;# Activate the environment and run a command&lt;/span&gt;
pipenv run &amp;lt;COMMAND&amp;gt; &lt;span class="c"&gt;# pipenv run python main.py&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;pipenv run &amp;lt;COMMAND&amp;gt;&lt;/code&gt; means to run &lt;code&gt;pipenv shell&lt;/code&gt; and then run &lt;code&gt;&amp;lt;COMMAND&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://rinatz.github.io/python-book/ch04-05-pipenv/"&gt;pipenv run &amp;lt;command&amp;gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Other commands
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Show the path of the virtual environment (directory)&lt;/span&gt;
pipenv &lt;span class="nt"&gt;--venv&lt;/span&gt;

&lt;span class="c"&gt;# Remove the local virtual environment with the whole installed packages&lt;/span&gt;
pipenv &lt;span class="nt"&gt;--rm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://qiita.com/RW_876/items/ce42026884f1383e21da"&gt;Command list (ja)&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
    </item>
    <item>
      <title>How can a client receive the cookie from a server-side?</title>
      <dc:creator>I.G</dc:creator>
      <pubDate>Sun, 24 Sep 2023 16:37:54 +0000</pubDate>
      <link>https://dev.to/igfreetech/how-can-a-client-receive-the-value-by-set-cookie-on-server-side-gkh</link>
      <guid>https://dev.to/igfreetech/how-can-a-client-receive-the-value-by-set-cookie-on-server-side-gkh</guid>
      <description>&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A client-side can receive the cookie from a server-side configuring "SameSite=none" when performing set-cookie.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;But you need to configure Secure attribute as well, otherwise the current modern browsers don't store the cookie for security.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Environment
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Frontend: React&lt;/li&gt;
&lt;li&gt;Serverside: API Gateway + Lambda + FastAPI(Python)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Server-side
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# functions/hub.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;mangum&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Mangum&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;.routers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;authentication_router&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;include_router&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;authentication_router&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"authentication"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;CORSMiddleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;allow_origins&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;allow_credentials&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;allow_methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;allow_headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Mangum converts a request and response of FastAPI into event and context of AWS Lambda.
&lt;/span&gt;&lt;span class="n"&gt;lambda_handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Mangum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;FastAPI restricts OPTIONS requests (preflight requests) by default, so even if you allow them on the API Gateway side, if you do not allow them on the FastAPI side, a 405 error will be returned.&lt;/p&gt;

&lt;p&gt;So, you need to explicitly include CORS headers in the response in FastAPI middleware so that the browser can make preflight requests.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# functions/routers/authentication.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;APIRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt;

&lt;span class="n"&gt;authentication_router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;APIRouter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RequestBody&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;authentication_router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/signin"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sign_in&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requset_body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;RequestBody&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;respose&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="c1"&gt;# Get tokens from Cognito
&lt;/span&gt;  &lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;signin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requset_body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requset_body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_cookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"access_token"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;access_token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;httponly&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;secure&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;samesite&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"none"&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Enabling HttpOnly, prevent the cookie from being accessed by JavaScript like &lt;code&gt;document.cookie&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enabling Secure, the cookie is send only via HTTPS. HTTP is prohibited to send it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;"Samesite=none" is to allow the cookie to be sent over a cross-site request. (e.g. from &lt;code&gt;example.apigateway.com&lt;/code&gt; to &lt;code&gt;example.vercel.app&lt;/code&gt; as below)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;API Gateway&lt;/th&gt;
&lt;th&gt;Vercel&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;example.apigateway.com&lt;/td&gt;
&lt;td&gt;example.vercel.app&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h5&gt;
  
  
  Remarks
&lt;/h5&gt;

&lt;p&gt;If configuring "SameSite=Lax" or "SameSite=Strict", client-side can't receive the cookie from the server-side.&lt;/p&gt;

&lt;p&gt;※Exclaimation mark is displayed at the header of set-cookie in the Network tab of the dev tool of your browser with the mesasge (e.g. "This attempt to set a cookie via a Set-Cookie header was blocked because it had the "SameSite=Lax" attribute but came from a cross-site response which was not the response to a top-level navigation.")&lt;/p&gt;

&lt;h5&gt;
  
  
  Configuration for Serverless Framework
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# serverless.yml&lt;/span&gt;
&lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;httpApi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;cors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;allowedOrigins&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;https://example.vercel.app&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;http://localhost:3000&lt;/span&gt;
      &lt;span class="na"&gt;allowedHeaders&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Content-Type&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Set-Cookie&lt;/span&gt;
      &lt;span class="na"&gt;allowedMethods&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;OPTIONS&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;GET&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POST&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;PUT&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;DELETE&lt;/span&gt;
      &lt;span class="na"&gt;allowCredentials&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

&lt;span class="na"&gt;functions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;hub&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hub&lt;/span&gt;
    &lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hub.lambda_handler&lt;/span&gt;
    &lt;span class="na"&gt;events&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
     &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;httpApi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
       &lt;span class="c1"&gt;# ANY method is used to catch all HTTP methods&lt;/span&gt;
       &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;any&lt;/span&gt;
       &lt;span class="c1"&gt;# /{proxy+} route works as a catch-all route&lt;/span&gt;
       &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/{proxy+}&lt;/span&gt;


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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Only the origins in allowedOrigins can access API Gateway.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Setting allowCredentials to true, enables cookies to be sent across domains.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;/{proxy+} catches all requests that don't match other routes already configured in API Gateway.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>react</category>
      <category>backend</category>
      <category>python</category>
      <category>aws</category>
    </item>
  </channel>
</rss>
