<?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: DrKnoxy</title>
    <description>The latest articles on DEV Community by DrKnoxy (@adamwknox).</description>
    <link>https://dev.to/adamwknox</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%2F6724%2Feu0evrce21pde5c6qmf4.jpeg</url>
      <title>DEV Community: DrKnoxy</title>
      <link>https://dev.to/adamwknox</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/adamwknox"/>
    <language>en</language>
    <item>
      <title>Follow along stream of a side project</title>
      <dc:creator>DrKnoxy</dc:creator>
      <pubDate>Tue, 06 Aug 2019 22:40:41 +0000</pubDate>
      <link>https://dev.to/adamwknox/follow-along-stream-of-a-side-project-305o</link>
      <guid>https://dev.to/adamwknox/follow-along-stream-of-a-side-project-305o</guid>
      <description>&lt;p&gt;Hey i'm thinking of doing a live stream while I build out an idea for a side project.&lt;/p&gt;

&lt;p&gt;stack: nextjs, react, firebase&lt;/p&gt;

&lt;p&gt;concept: a travel journey focused on writing &lt;br&gt;
set apart: not focused on image only, focus on wysiwyg experience over twitter style limit.&lt;/p&gt;

&lt;p&gt;not sure how far i'll get tonight&lt;/p&gt;

&lt;p&gt;50 replies and i'll start a live stream!&lt;/p&gt;

&lt;p&gt;About me: 10y dev experience, 3y with react 😁 arright&lt;/p&gt;

</description>
      <category>firebase</category>
      <category>react</category>
      <category>javascript</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>I made a mistake implementing a React Hook and got a denial of service from my backend</title>
      <dc:creator>DrKnoxy</dc:creator>
      <pubDate>Thu, 20 Dec 2018 01:53:55 +0000</pubDate>
      <link>https://dev.to/adamwknox/i-made-a-mistake-implementing-a-react-hook-and-got-a-denial-of-service-from-my-backend-5cji</link>
      <guid>https://dev.to/adamwknox/i-made-a-mistake-implementing-a-react-hook-and-got-a-denial-of-service-from-my-backend-5cji</guid>
      <description>&lt;p&gt;This seemingly simple usage of React's useEffect hook on a Firebase endpoint accidentally ran through my 50k reads/day quota in minutes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;Page&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;meetings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setMeetings&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="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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firestore&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/meetings&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;onSnapshot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&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;setMeeting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;m&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;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;ul&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;meetings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&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;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&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;li&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;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&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;The effect isn't dependent on any state changing so I omitted the second parameter. What I failed to realize was that everytime &lt;code&gt;setMeeting&lt;/code&gt; was called the body of the function would be executed again, causing a loop in the data fetching.&lt;/p&gt;

&lt;p&gt;So yeah. Firebase's free tier offers a 50k reads/day quota that I exceeded in a few minutes of development work. It was a pain to trace down too. Once I realized that the Net tab in Chrome devtools was pounding out requests to firebase I had to hurry over to the perf tab and move into "offline mode". Then I had the time to take a look at the payload of one of the requests and figure out what data was being requested.&lt;/p&gt;

&lt;p&gt;The fix is simply to add an empty square brace to indicate that this should only be run once, kind of like only componentDidMount and componentWillUnmount (the return from the firebase call is a listener we want to unmount).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&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="c1"&gt;// return firebase...&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="c1"&gt;// this guy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After I fixed it though I paused and thought about the underlying problems.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;It is really easy to overlook the second parameter in an effect hook.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There is no server side rate-limiting implementation for firebase / firestore. So any malicious user, or a bug in the code, can take down a free tier or charge a ton of money to a paying user. There wasn't even a great way to visualize what endpoint was being hammered, or when, by the quota management tool in Google's console.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When your usage quota is exceeded in Firebase you can't even access your admin panel.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Error handling doesn't catch this kind of thing.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Happy Hacking,&lt;/p&gt;




&lt;p&gt;References&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Photo by Andrew Gaines on Unsplash&lt;/li&gt;
&lt;li&gt;Firebase is a Backend as a Service providing a generous free-tier for a realtime data storage solution&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>firebase</category>
      <category>react</category>
    </item>
    <item>
      <title>Are you left with any proprietary advantage when building a Javascript app?</title>
      <dc:creator>DrKnoxy</dc:creator>
      <pubDate>Thu, 20 Dec 2018 00:00:02 +0000</pubDate>
      <link>https://dev.to/adamwknox/are-you-left-with-any-proprietary-advantage-when-building-a-javascript-app-3d01</link>
      <guid>https://dev.to/adamwknox/are-you-left-with-any-proprietary-advantage-when-building-a-javascript-app-3d01</guid>
      <description>&lt;p&gt;I'm using firebase to build a client side app that I intended to monetize. It occurred to me though that if source maps are accessible then I'm essentially publishing the entire source minus config, build, db rules, and a handful of cloud functions. &lt;/p&gt;

&lt;p&gt;Has anyone thought much about this? &lt;/p&gt;

</description>
      <category>discuss</category>
      <category>firebase</category>
    </item>
  </channel>
</rss>
