<?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: Michiel Mulders</title>
    <description>The latest articles on DEV Community by Michiel Mulders (@michielmulders).</description>
    <link>https://dev.to/michielmulders</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%2F169519%2Fa4381493-68bf-4437-b30c-06e3241612f2.jpg</url>
      <title>DEV Community: Michiel Mulders</title>
      <link>https://dev.to/michielmulders</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/michielmulders"/>
    <language>en</language>
    <item>
      <title>Exchange-Based Trading vs. CFD Trading - Which Is Best for YOU?</title>
      <dc:creator>Michiel Mulders</dc:creator>
      <pubDate>Mon, 05 Apr 2021 16:24:08 +0000</pubDate>
      <link>https://dev.to/michielmulders/exchange-based-trading-vs-cfd-trading-which-is-best-for-you-974</link>
      <guid>https://dev.to/michielmulders/exchange-based-trading-vs-cfd-trading-which-is-best-for-you-974</guid>
      <description>&lt;p&gt;Most people start trading cryptocurrencies through crypto exchanges, which is the most obvious option.&lt;/p&gt;

&lt;p&gt;However, there’s another option that allows traders to speculate on price movements without actually owning or holding the underlying cryptocurrency. We can achieve this type of trading using contracts for difference (CFDs), an instrument that’s very popular in the world of stock trading. &lt;/p&gt;

&lt;p&gt;But how does a CFD work, and why would you use it? This article explores crypto CFDs and compares them against exchange-based trading.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Contract For Difference (CFD)?
&lt;/h2&gt;

&lt;p&gt;First, let’s dive a bit deeper into the ‘What’ of CFDs. Trading contracts for difference is a way of speculating on financial markets that don’t require the buying and selling of any underlying assets. When you trade a CFD, you agree to exchange the difference in the price of an asset from the point at which the contract is opened to when it is closed. You can create such contracts via CFD brokers.&lt;/p&gt;

&lt;p&gt;The main benefit of this approach is that you can speculate on price movements in either direction. For instance, you expect the price of Bitcoin to enter a bear market for the upcoming months. It’s a great entry point for opening a short contract with a CFD broker. More on this strategy later.&lt;/p&gt;

&lt;p&gt;So, what are the pros and cons of cryptocurrency CFD trading?&lt;/p&gt;

&lt;h2&gt;
  
  
  Cryptocurrency CFD Trading vs Exchange-based Trading
&lt;/h2&gt;

&lt;p&gt;Here’s a list of arguments that favor CFD trading or exchange-based crypto trading.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. CFD: Cheaper option for leveraged trading
&lt;/h3&gt;

&lt;p&gt;CFDs offer a cheaper alternative for leveraged trading. Many crypto traders avoid opening leveraged positions due to the high fees exchanges charge. It’s certainly not a good idea to open a long-term leveraged position via a crypto exchange.&lt;/p&gt;

&lt;p&gt;Some exchanges charge up to 0.02% to open a position and up to 0.02% (per 4 hours) in rollover fees to keep it open. This means you’ll pay six times per day a fee of 0.02% on your total position. In other words, fees accumulate rapidly and discourage traders from opening long-term leveraged positions.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Exchange: A wider variety of crypto pairs
&lt;/h3&gt;

&lt;p&gt;While CFD trading might be cheaper for opening leveraged or short positions, you are often limited in the variety of cryptocurrencies offered. Some crypto exchanges offer more than 300 cryptocurrency pairs for you to choose from. For instance, popular crypto exchange Binance offers its users 1132 crypto pairs.&lt;/p&gt;

&lt;p&gt;Some exchanges charge up to 0.02% to open a position and up to 0.02% (per 4 hours) in rollover fees to keep it open. This means you’ll pay six times per day a fee of 0.02% on your total position. In other words, fees accumulate rapidly and discourage traders from opening long-term leveraged positions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wZSGfUB3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ls5o7e2u1rke0us79wbm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wZSGfUB3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ls5o7e2u1rke0us79wbm.png" alt="CoinMarketCap"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Screenshot: CoinMarketCap.com)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;However, a CFD broker &lt;a href="https://www.easymarkets.com/au/en-au/trade/bitcoin/?ref=hackernoon.com"&gt;like easyMarkets&lt;/a&gt; typically offers the most popular cryptocurrencies such as Bitcoin, Ripple, Ethereum, Litecoin, Bitcoin Cash, and Stellar. And most CFD traders prefer to trade cryptocurrencies with a lot of volume like the cryptos as mentioned earlier. As you would have guessed, Bitcoin trading is most popular for CFD trading.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vvtx6Qz8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1ssri4yav89c1u7vchqt.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vvtx6Qz8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1ssri4yav89c1u7vchqt.jpg" alt="CFD Trading"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Screenshot: easyMarkets.com Bitcoin trading)&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. CFD: Great for hedging risks
&lt;/h3&gt;

&lt;p&gt;Traders want to find new ways to protect their trades. Hedging is one such example of protecting a trade against volatility or external circumstances that can affect a cryptocurrency’s price.&lt;/p&gt;

&lt;p&gt;Most often, traders use hedging to offset the risk of their position by opening a trade in the other direction when the market is unclear or they are concerned about the stability of the market. &lt;/p&gt;

&lt;p&gt;For instance, you want to hold Bitcoin long-term, but you expect the Bitcoin market to turn into a short-term bear market. To offset the risk of this bear market, you can open a short position via CFDs. In other words, if the market falls, you can cover some of the loss to your initial position with the gain from this short position. &lt;/p&gt;

&lt;p&gt;The most common types of risk include but are not limited to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Crypto hacks&lt;/li&gt;
&lt;li&gt;Smart contract failure&lt;/li&gt;
&lt;li&gt;High market volatility&lt;/li&gt;
&lt;li&gt;Regulatory risks&lt;/li&gt;
&lt;li&gt;Entering a bear or bull market&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Exchange: You own the cryptocurrency
&lt;/h3&gt;

&lt;p&gt;When using an exchange to trade cryptocurrency, you can choose between an exchange that uses hot wallets or one that allows you to generate new wallets to which you own the private and public keys. &lt;/p&gt;

&lt;p&gt;When you want to truly own your crypto, you should pick an exchange that provides you with the private and public keys of your crypto wallet.&lt;/p&gt;

&lt;p&gt;When trading CFDs, you don’t own any crypto. A CFD is a derivative instrument that is merely used for speculation. If you want to truly own Bitcoin or any other cryptocurrency, your best choice is to pick an exchange that gives you access to your crypto wallet. You can also buy cryptocurrencies and send them to a non-custodial wallet you own. &lt;/p&gt;

&lt;h3&gt;
  
  
  5. CFD: Better risk management tools
&lt;/h3&gt;

&lt;p&gt;By now, most exchanges and CFD brokers offer risk management instruments or tools such as setting a &lt;a href="https://www.youtube.com/watch?v=5-LYiCyKcyE&amp;amp;ref=hackernoon.com"&gt;Take-profit or a Stop-loss order&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;However, CFD brokers like easyMarkets offer users other protection mechanisms. For instance, they protect users against negative balances, which means you can’t lose more money than you’ve deposited. It’s a promise many crypto exchanges can’t always guarantee. When trading, you don’t want to worry about the possibility of losing more money than you initially planned as the worst-case scenario.&lt;/p&gt;

&lt;p&gt;Besides that, they also offer a guaranteed stop-loss to ensure your position is closed at the pre-selected price. It’s an important risk management tool some exchanges can’t offer due to slippage during high volatility.&lt;/p&gt;

&lt;p&gt;In other words, CFD brokers understand the need for reliable &lt;a href="https://hackernoon.com/enhanced-risk-management-will-help-crypto-to-grow-sustainably-yv2633xg?ref=hackernoon.com"&gt;risk management tools&lt;/a&gt; for traders. It’s also one of the most important elements of trading.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s best: Crypto exchanges or CFD brokers?
&lt;/h2&gt;

&lt;p&gt;We can’t conclude on a definitive winner just looking at the above arguments. Both approaches have their own set of advantages. Yet, we can conclude the following.&lt;/p&gt;

&lt;p&gt;If you are a long-term crypto investor, you can use CFDs to hedge your position against any type of risk. Moreover, it’s much cheaper to use a CFD broker than to open a leveraged trade than to use a crypto exchange to hedge your risk.&lt;/p&gt;

&lt;p&gt;On the other hand, if you are a trader who likes to frequently open short positions, CFD trading might be a cheaper option for you. If you would like to explore CFD trading, easyMarkets is a great place to get started. They offer traders many built-in risk management solutions to make trading a more pleasant experience.&lt;/p&gt;

</description>
      <category>trading</category>
      <category>cfd</category>
      <category>crypto</category>
    </item>
    <item>
      <title>What are React Server Components and will you need to use them in the future?</title>
      <dc:creator>Michiel Mulders</dc:creator>
      <pubDate>Wed, 03 Feb 2021 10:26:31 +0000</pubDate>
      <link>https://dev.to/michielmulders/what-are-react-server-components-and-will-you-need-to-use-them-in-the-future-2oi3</link>
      <guid>https://dev.to/michielmulders/what-are-react-server-components-and-will-you-need-to-use-them-in-the-future-2oi3</guid>
      <description>&lt;p&gt;Around Christmas, the React team introduced &lt;a href="https://reactjs.org/blog/2020/12/21/data-fetching-with-react-server-components.html"&gt;React Server Components&lt;/a&gt;. It’s a complete surprise for the React ecosystem as React has always focused on the client-side with a small focus on server-side rendering. Server-side rendering can, for instance, be accomplished using Next.js. &lt;/p&gt;

&lt;p&gt;However, with React Server Components (RSC), it’s now possible to write server-rendered code using React only. Note that RSC is not a final feature as of now. Currently, React Server Components are undergoing beta-testing.&lt;/p&gt;

&lt;p&gt;In this article, you’ll learn the following concepts about React Server Components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What is a React Server Component?&lt;/li&gt;
&lt;li&gt;Why do we need React Server Components? What problems do they solve?&lt;/li&gt;
&lt;li&gt;What does a React Server Component look like, and what are the benefits?&lt;/li&gt;
&lt;li&gt;What’s the difference between React Server Components and Server Side Rendering (SSR)?&lt;/li&gt;
&lt;li&gt;Is there any future for React Server Components?&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What is a React Server Component?
&lt;/h2&gt;

&lt;p&gt;Let’s make this clear first: React always renders React Server Components on the server. It allows frontend developers to create components that span both server and client. &lt;/p&gt;

&lt;p&gt;Why is this useful? This property allows developers to quickly fetch data from the backend. Therefore, you don't have to send an expensive request from your client to your backend to fetch data. As you render your components on the server that also hosts your backend, you can make a local call to your API to fetch data. In other words, locally fetched data is super fast (cheap).&lt;/p&gt;

&lt;p&gt;To summarize, React Server Components allow you to access the speed of fetching data on the server-side while maintaining its rich interactivity of client-side apps. That’s a fantastic improvement for the React ecosystem to build faster applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why do we need React Server Components?
&lt;/h2&gt;

&lt;p&gt;UI development needs to offer the following properties:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It should offer a good user experience&lt;/li&gt;
&lt;li&gt;It should be cheap to maintain&lt;/li&gt;
&lt;li&gt;It should offer fast performance&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;However, these properties are at odds with each other. To illustrate this problem with the current state of React, let’s imagine a Spotify artist page that has the following components.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;ArtistPage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;artistID&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ArtistDetails&lt;/span&gt; &lt;span class="nx"&gt;artistId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;artistId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TopTracks&lt;/span&gt; &lt;span class="nx"&gt;artistId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;artistId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Discography&lt;/span&gt; &lt;span class="nx"&gt;artistId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;artistId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ArtistDetails&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let’s fetch all data at the top of the component and pass each component’s required data. This approach’s benefit is that it’s performant as we only send one API call to retrieve all data we need.&lt;/p&gt;

&lt;p&gt;We end up with the below code.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;ArtistPage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;artistID&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;artistData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fetchAllArtistData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ArtistDetails&lt;/span&gt; 
      &lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;artistData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;artistId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;artistId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TopTracks&lt;/span&gt; 
        &lt;span class="nx"&gt;topTracks&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;artistData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;topTracks&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;artistId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;artistId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Discography&lt;/span&gt; 
        &lt;span class="nx"&gt;discography&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;artistData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;discography&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;artistId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;artistId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ArtistDetails&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API response becomes very coupled to the component. We expect the API call to return artist details, top tracks, and discography. If we want to change the component’s behavior in the future, we might need to change the behavior of the API endpoint as well. &lt;/p&gt;

&lt;p&gt;Further, if we remove a component inside the &lt;code&gt;&amp;lt;ArtistDetail/&amp;gt;&lt;/code&gt; component, we might forget to remove this data from the API call. Therefore, this approach affects code maintenance. But don't worry, there’s nothing fundamentally wrong with this approach. It’s how React works.&lt;/p&gt;

&lt;p&gt;What if we allow each component to fetch its data to decouple the API response from the component? Our code might look like this.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;ArtistDetails&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;artistId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;children&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;artistData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fetchDetails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;artistId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;
  // ...
}

function TopTracks({ artistId }) {
  const topTracks = fetchTopTracks(artistId)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&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;Discography&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;artistId&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;discography&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fetchDiscography&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;artistId&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While this code is much easier to maintain, it creates performance issues. If you remember our initial component, we’ll get a cascade of API calls that wait for each other to finish. &lt;/p&gt;

&lt;p&gt;In other words, the &lt;code&gt;&amp;lt;ArtistDetails/&amp;gt;&lt;/code&gt; component fetches data, then &lt;code&gt;&amp;lt;TopTracks/&amp;gt;&lt;/code&gt; fetches its data, and finally, the &lt;code&gt;&amp;lt;Discography/&amp;gt;&lt;/code&gt; component starts fetching the required data. They also call this a network waterfall.&lt;/p&gt;

&lt;p&gt;Our previous example used a single API call to fetch all data to increase performance.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;ArtistPage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;artistID&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ArtistDetails&lt;/span&gt; &lt;span class="nx"&gt;artistId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;artistId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TopTracks&lt;/span&gt; &lt;span class="nx"&gt;artistId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;artistId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Discography&lt;/span&gt; &lt;span class="nx"&gt;artistId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;artistId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ArtistDetails&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, can we come up with a solution that addresses all three properties in the React ecosystem: good UX, cheap maintenance, and fast performance? The potential answer here is React Server Components (RSC) by moving our components to the server.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does a React Server Component look like?
&lt;/h2&gt;

&lt;p&gt;It’s time to explore a React Server Component. This component is an example out of the &lt;a href="https://github.com/reactjs/server-components-demo/blob/main/src/NoteList.server.js"&gt;React demo&lt;/a&gt; for React Server Components. We have a list of notes that we can expand when we click it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can distinguish a server-side component from a client-side component by appending the file name with &lt;code&gt;.server.js&lt;/code&gt;. The file below is named &lt;code&gt;NoteList.server.js&lt;/code&gt;. You can apply the opposite for a client-side file: &lt;code&gt;myFile.client.js&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// NoteList.server.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;SidebarNote&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;./SidebarNote&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;NoteList&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;searchText&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;notes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:4000/notes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;notes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ul&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;notes-list&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;notes&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;note&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;li&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;note&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;SidebarNote&lt;/span&gt; &lt;span class="nx"&gt;note&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;note&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/li&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;))}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ul&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;notes-empty&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;searchText&lt;/span&gt;
        &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;`Couldn't find any notes titled "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;searchText&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No notes created yet!&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; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First of all, we can immediately fetch notes data from the server using &lt;code&gt;http://localhost:4000/notes&lt;/code&gt;. This ticks off the fast performance property. On top of that, we can use interactive logic on our server, such as &lt;code&gt;return notes.length &amp;gt; 0 ? &amp;lt;code&amp;gt;  : &amp;lt;code&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next, let’s look at an example where we have an import that we only use once to format dates &lt;code&gt;data-fns&lt;/code&gt;. Often, front-end developers have to evaluate if they want to include a dependency that they only use once or twice in the application. It will increase the final bundle size. Developers often ask the question: is it worth it?&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;format&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isToday&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;date-fns&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;SidebarNote&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;note&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;updatedAt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;note&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;updated_at&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;lastUpdatedAt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;isToday&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updatedAt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updatedAt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h:mm bb&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="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updatedAt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;M/d/yy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sidebar-note-list-item&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sidebar-note-header&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;strong&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;note&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/strong&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;small&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;lastUpdatedAt&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/small&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/header&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;classname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sidebar-note-open&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With React Server Components, we don’t have to worry about this evaluation. React won’t include a dependency that you use only in a React Server Component in the bundle size. Therefore, the user won’t have to download this dependency. The RSC will use this dependency on the server to render the required output and send this output to the client. Cool, right?&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s the difference between React Server Components and Server Side Rendering (SSR)?
&lt;/h2&gt;

&lt;p&gt;Server-side rendering focuses on reducing the initial page load. When using SSR, you send HTML to the client. The client then loads all of the React JavaScript you need to make your web page interactive. In other words, you have a traditional React app after the initial page load when React injects all JavaScript. &lt;/p&gt;

&lt;p&gt;The most significant difference is that your components are still client-side components. All required dependencies are still downloaded. The only difference when using SSR is that your initial page load contains only HTML to improve performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is there any future for React Server Components?
&lt;/h2&gt;

&lt;p&gt;There’s a massive potential for React Server Components as they address many tradeoffs React developers experience. Some of the most important benefits include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fast data fetching locally on a server&lt;/li&gt;
&lt;li&gt;Server-side dynamic logic&lt;/li&gt;
&lt;li&gt;Ability to include any dependency for RSCs without having to worry about increasing the cost to load a web page&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the other hand, many React users might get confused at first by this domain switch. React has shown a strong focus on the client-side in the past. React Server Components suddenly span both server and client. This change requires a significant shift in the way we think about React components. &lt;/p&gt;

&lt;p&gt;For that reason, I expect React developers to embrace this approach but also to see many people struggle to grasp this concept and make correct decisions about server/client-side components.&lt;/p&gt;

&lt;p&gt;If you want to play around with the demo code for React Server Components, you can find this code on &lt;a href="https://github.com/reactjs/server-components-demo"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Fetch vs Axios: Which Is the Best Library for Making HTTP Requests?</title>
      <dc:creator>Michiel Mulders</dc:creator>
      <pubDate>Mon, 01 Feb 2021 23:21:14 +0000</pubDate>
      <link>https://dev.to/michielmulders/fetch-vs-axios-which-is-the-best-library-for-making-http-requests-4mpd</link>
      <guid>https://dev.to/michielmulders/fetch-vs-axios-which-is-the-best-library-for-making-http-requests-4mpd</guid>
      <description>&lt;p&gt;In our previous post &lt;a href="https://blog.asayer.io/how-to-make-http-requests-with-axios"&gt;“How to make HTTP requests with Axios&lt;/a&gt;,” we’ve explained how to use Axios for sending basic CRUD requests. One of the main benefits of using Axios is the automatic JSON stringification when sending requests. A feature not supported by the native &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API"&gt;Fetch API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Our post concluded that Axios is a lightweight library that offers a lot of helpful functionality when dealing with HTTP requests. For example, Axios provides an easy way to track upload progress via its request config. Moreover, Axios allows you to define interceptors to automate specific tasks for requests easily.&lt;/p&gt;

&lt;p&gt;However, let’s also take a look at the Fetch API. You can perform the same tasks with the Fetch API. On top of that, the Fetch API is already available in all modern browsers.&lt;/p&gt;

&lt;p&gt;This article aims to provide you with an overview of both tools so you can make a better-informed decision when picking a tool to send HTTP requests.&lt;/p&gt;

&lt;p&gt;We’ll compare:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CRUD operations&lt;/li&gt;
&lt;li&gt;Automatic JSON parsing&lt;/li&gt;
&lt;li&gt;Interceptors&lt;/li&gt;
&lt;li&gt;Error handling&lt;/li&gt;
&lt;li&gt;Request timeout functioning&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Comparison: CRUD operations and automatic JSON parsing
&lt;/h2&gt;

&lt;p&gt;Let’s first take a look at sending basic requests. Let’s retrieve some data from a publicly available API at &lt;a href="https://jsonplaceholder.typicode.com/todos/"&gt;typicode.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First, the Axios object exposes different methods to retrieve, send, update, or delete a resource from an API. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;axios.get(url[, config])&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;axios.post(url[, data[, config]])&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;axios.put(url[, data[, config]])&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;axios.patch(url[, data[, config]])&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;axios.delete(url[, config])&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a &lt;code&gt;GET&lt;/code&gt; request, the function accepts an API URL and an optional configuration object.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://jsonplaceholder.typicode.com/todos/1&lt;/span&gt;&lt;span class="dl"&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;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&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;error&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;getRequest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can use the &lt;code&gt;config&lt;/code&gt; object to send additional parameters or headers. You can find all possible &lt;a href="https://github.com/axios/axios#request-config"&gt;request configuration parameters&lt;/a&gt; in the Axios documentation.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://jsonplaceholder.typicode.com/todos&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;headers&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;X-Custom-Header&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;foobar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let’s take a look at the &lt;code&gt;fetch()&lt;/code&gt; version. The fetch API is the same as the Axios API. Note that you can pass any method to the &lt;code&gt;fetch()&lt;/code&gt; function via the &lt;code&gt;options&lt;/code&gt; object.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;fetch(url, [options])&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, it accepts an API URL and an &lt;code&gt;options&lt;/code&gt; object. We have to pass the method with the options object. Further, we can also pass headers, parameters, or a body with this object.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&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;Accept&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;application/json&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;Content-Type&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;application/json;charset=UTF-8&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="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://jsonplaceholder.typicode.com/todos/1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note how we have to manually parse the resolve response object to JSON before we can log the returned data. Axios automatically takes care of parsing the response to JSON.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison: Interceptors
&lt;/h2&gt;

&lt;p&gt;Axios provides &lt;a href="https://github.com/axios/axios#interceptors"&gt;interceptors&lt;/a&gt; for both requests and responses. In other words, you can modify a request before sending it to an API or modify a response object that’s been returned. It’s a powerful concept that allows the automation of specific tasks. &lt;/p&gt;

&lt;p&gt;You can use request interceptors to automatically add authorization headers. Furthermore, response interceptors are useful for modifying the response object to fit a different format. It’s even possible to intercept error responses and send them to a monitoring tool.&lt;/p&gt;

&lt;p&gt;Here’s an example of an Axios interceptor used in our previous tutorial.The &lt;code&gt;axios.interceptors.request.use()&lt;/code&gt; method allows you to define a request interceptor.&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="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interceptors&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;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&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;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-axios-app&lt;/span&gt;&lt;span class="dl"&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="s2"&gt;`Sending &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; request to: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;config&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="s2"&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;config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;error&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// send GET request&lt;/span&gt;
&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://jsonplaceholder.typicode.com/todos/1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How can we do this with &lt;code&gt;fetch()&lt;/code&gt;? By default, &lt;code&gt;fetch()&lt;/code&gt; doesn’t support a way to define request interceptors. Luckily, we can fall back to overwriting the function so we can add custom logic to the fetch method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;originalFetch&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="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;arguments&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Adding headers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="nx"&gt;arguments&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="nx"&gt;headers&lt;/span&gt; &lt;span class="o"&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;Accept&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;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;originalFetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;arguments&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;fetch&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://jsonplaceholder.typicode.com/todos/1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&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="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&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;data&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;As you can see, overwriting the original &lt;code&gt;fetch()&lt;/code&gt; function affects the readability of your code. Personally, I prefer using Axios’ request and response interceptors. Yet, there’s an NPM package that allows you to register custom interceptors to the &lt;code&gt;fetch()&lt;/code&gt; method in a more readable manner. The package is called &lt;a href="https://www.npmjs.com/package/fetch-intercept"&gt;fetch-intercept&lt;/a&gt;. Here's an example that solves the problem.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchIntercept&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fetch-intercept&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;unregister&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fetchIntercept&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&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;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Modify the url or config here&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="s2"&gt;`Sending &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; request to: &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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;

    &lt;span class="na"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Modify the reponse object&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Response received&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&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="c1"&gt;// Call fetch to see your interceptors in action.&lt;/span&gt;
&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://jsonplaceholder.typicode.com/todos/1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Unregister your interceptor&lt;/span&gt;
&lt;span class="nx"&gt;unregister&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, let’s learn how both tools take care of error handling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison: Error handling
&lt;/h2&gt;

&lt;p&gt;It’s essential to understand the difference between Axios and &lt;code&gt;fetch()&lt;/code&gt; in error handling. When Axios receives a 404 or 400 error, it will catch the error using the &lt;code&gt;catch()&lt;/code&gt; block. This &lt;code&gt;catch()&lt;/code&gt; block allows you to handle the error.&lt;/p&gt;

&lt;p&gt;Instead, the Fetch API prefers completing the request successfully via the &lt;code&gt;then()&lt;/code&gt; method but includes a 400 status. We can also find this in the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API#differences_from_jquery"&gt;&lt;code&gt;fetch()&lt;/code&gt; documentation&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The Promise returned from fetch() won’t reject for a HTTP error status even if the response is an HTTP 404 or 500. Instead, it will resolve normally (with ok status set to false), and it will only reject on network failure or if anything prevented the request from completing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can try it out yourself using the below code.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://jsonplaceholder.typicode.com/toodoos/1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&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="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;good&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// enters catch method -&amp;gt; prints 404&lt;/span&gt;

&lt;span class="nx"&gt;fetch&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BAD&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GOOD&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusText&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// enters then method -&amp;gt; prints 404 status&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the end, this is a personal preference. Some industry experts argue that the request didn’t fail, so it finished successfully. This is independent from whether the server could find the resource or not. &lt;/p&gt;

&lt;p&gt;However, it’s a significant difference to know when working with one of both libraries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison: How to timeout a request?
&lt;/h2&gt;

&lt;p&gt;Having the ability to define a timeout for a request prevents your application from &lt;em&gt;hanging&lt;/em&gt; requests. These hanging requests can slow down your application or cause a memory leak, and therefore, are pretty dangerous.&lt;/p&gt;

&lt;p&gt;As indicated by &lt;a href="https://robertovitillo.com/default-timeouts/"&gt;Roberto Vitillo&lt;/a&gt;, “Modern applications don’t crash; they hang. One of the main reasons for it is the assumption that the network is reliable. It isn’t.”&lt;/p&gt;

&lt;p&gt;So, how do &lt;code&gt;fetch()&lt;/code&gt; and Axios handle request timeouts?&lt;/p&gt;

&lt;p&gt;First, Axios doesn’t set a default timeout. Therefore, it relies on the browser's request timeout. In Chrome, a network request times out at 300 seconds. That’s way too long. Let’s change that using the &lt;code&gt;config&lt;/code&gt; object. The example below aborts the request after a 1000 milliseconds waiting time.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://jsonplaceholder.typicode.com/todos/1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;timeout&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For &lt;code&gt;fetch()&lt;/code&gt;, there was originally &lt;a href="https://github.com/whatwg/fetch/issues/951"&gt;no way to set a timeout&lt;/a&gt;. Luckily, we can make use of the experimental &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/AbortController#examples"&gt;Abort API&lt;/a&gt; that supports request timeouts. Here’s an example of how to abort a request after 1000ms with &lt;code&gt;fetch()&lt;/code&gt;.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;AbortController&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;fetchPromise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://jsonplaceholder.typicode.com/todos/1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;  

&lt;span class="c1"&gt;// Abort request using setTimeout&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="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;abort&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="nx"&gt;fetchPromise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&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;// Finished request&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;response&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;Note how we use the &lt;code&gt;AbortController&lt;/code&gt; and pass the abort signal via our &lt;code&gt;config&lt;/code&gt; object to the &lt;code&gt;fetch()&lt;/code&gt; method. Once the &lt;code&gt;setTimeout()&lt;/code&gt; timer runs out, it will call the &lt;code&gt;abort()&lt;/code&gt; method on the controller object. This abort call will send the abort signal to our &lt;code&gt;fetch()&lt;/code&gt; call.&lt;/p&gt;

&lt;p&gt;Again, &lt;code&gt;fetch()&lt;/code&gt; opts for a more lengthy workaround to implement a timeout for requests.&lt;/p&gt;

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

&lt;p&gt;Axios provides a more comfortable to use API in comparison with &lt;code&gt;fetch()&lt;/code&gt;. The most significant disadvantage of using &lt;code&gt;fetch()&lt;/code&gt; is the verbose workaround to set a timeout for your request. It’s a much-needed functionality to prevent hanging requests. &lt;/p&gt;

&lt;p&gt;On the other hand, remember that Axios sets the default timeout to zero. Therefore, don’t forget to set a timeout for each request. Alternatively, you can use a request interceptor to automatically set the request timeout.&lt;/p&gt;

&lt;p&gt;Furthermore, for Node.js especifically, automatic JSON parsing is a useful feature to keep your code clean. Again, you can use an interceptor for the Fetch API to parse a response object automatically to JSON. &lt;/p&gt;

&lt;p&gt;Yet, as seen in this guide, we have to overwrite the &lt;code&gt;fetch()&lt;/code&gt; method to add custom logic. I think it adds complexity to your code. For that reason, Axios is a clear winner to send HTTP requests based on its simplicity and ease-of-use.&lt;/p&gt;

</description>
      <category>react</category>
      <category>reactnative</category>
      <category>testing</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Why Use Redux - Reasons With Clear Examples</title>
      <dc:creator>Michiel Mulders</dc:creator>
      <pubDate>Wed, 20 Jan 2021 22:00:10 +0000</pubDate>
      <link>https://dev.to/michielmulders/why-use-redux-reasons-with-clear-examples-1108</link>
      <guid>https://dev.to/michielmulders/why-use-redux-reasons-with-clear-examples-1108</guid>
      <description>&lt;p&gt;Redux is a pattern and library for managing and updating application state, using events called "actions". In other words, the Redux pattern provides state management for JavaScript apps. You can use the Redux library with any frontend framework, such as React, Angular, or even Vue. In the end, you can implement the Redux pattern in any vanilla JS application. &lt;/p&gt;

&lt;p&gt;This article covers what Redux is, why you need it, how it works, the benefits, and when not to use Redux. To make Redux clearer, we’ll update you with code examples to make the concept easier to grasp. Let’s get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Redux?
&lt;/h2&gt;

&lt;p&gt;As mentioned in the introduction, Redux is a pattern that facilitates state management. It allows you to maintain a predictable state container for your JavaScript apps. This is important for consumer-facing applications where the interface changes based on user input. &lt;/p&gt;

&lt;p&gt;On top of that, Redux prevents race conditions where two components simultaneously try to update the state. It accomplishes this task by defining actions that get dispatched to reducers. &lt;/p&gt;

&lt;p&gt;Each action contains a type (also seen as an identifier) and a payload. Next, a reducer accepts the action and changes the state based on the received action type and payload.&lt;/p&gt;

&lt;p&gt;Reducers are pure functions, which means they are predictable. A pure function returns the same output for the same input. You can use reducers to generate a new application state.&lt;/p&gt;

&lt;p&gt;Lastly, to notify our interface that the application state has changed, we can subscribe to data changes. Whenever the application state changes, we update the UI.&lt;/p&gt;

&lt;p&gt;It’s a simple, yet elegant solution to facilitate predictable state management for small and large applications. Luckily, most popular frameworks offer support for Redux. Here's a quick overview:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;React&lt;/strong&gt; -&amp;gt; &lt;a href="https://www.npmjs.com/package/react-redux" rel="noopener noreferrer"&gt;react-redux&lt;/a&gt;: You can add Redux to your React application by installing the &lt;code&gt;react-redux&lt;/code&gt; dependency. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Angular&lt;/strong&gt; -&amp;gt; &lt;a href="https://www.npmjs.com/package/@ngrx/store" rel="noopener noreferrer"&gt;@ngrx/store&lt;/a&gt; or &lt;a href="https://www.npmjs.com/package/@angular-redux/store" rel="noopener noreferrer"&gt;@angular-redux/store&lt;/a&gt;: Both options work well to implement Redux into your Angular application. According to &lt;a href="https://www.npmtrends.com/@angular-redux/store-vs-@ngrx/store-vs-@ngxs/store" rel="noopener noreferrer"&gt;npmtrends.com&lt;/a&gt;, &lt;code&gt;@angular-redux/store&lt;/code&gt; is the most popular library in terms of weekly downloads.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Vue&lt;/strong&gt; -&amp;gt; &lt;a href="https://www.npmjs.com/package/vuejs-redux" rel="noopener noreferrer"&gt;vuejs-redux&lt;/a&gt;: This dependency offers a light-weight implementation of Redux for Vue with only 45 lines of code and no dependencies. It provides the same API as the &lt;code&gt;react-redux&lt;/code&gt; dependency.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next, why should you use Redux?&lt;/p&gt;

&lt;h2&gt;
  
  
  Why use Redux?
&lt;/h2&gt;

&lt;p&gt;Instead of directly exploring examples, let’s learn more about the problem Redux solves. &lt;/p&gt;

&lt;p&gt;As with many applications, they start small. Imagine a pyramid structure of seven components where each component as two child components. Each component manages its state. However, situations occur where we have to share a state with a child component or a child component wants to modify the parent component’s state.&lt;/p&gt;

&lt;p&gt;Do you see the problem? While our application grows to a higher number of components, maintaining data consistency becomes a hairy challenge. It’s not an easy task to manage each component’s state while sharing it with many other components. You’ll likely experience data inconsistency bugs, a fearsome nightmare for frontend developers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.codecentric.de%2Ffiles%2F2017%2F12%2FBildschirmfoto-2017-12-01-um-08.53.32.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.codecentric.de%2Ffiles%2F2017%2F12%2FBildschirmfoto-2017-12-01-um-08.53.32.png" alt="without Redux vs. with Redux"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Image source: &lt;a href="https://blog.codecentric.de/en/2017/12/developing-modern-offline-apps-reactjs-redux-electron-part-3-reactjs-redux-basics/" rel="noopener noreferrer"&gt;Codecentric blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As shown in the image, Redux takes away the responsibility from individual components to manage a state. Instead, we create a single store that handles our state management. On top of that, all communication regarding reading, updating, or creating data happens via the store. It prevents data inconsistency bugs from appearing. Moreover, components can listen to state changes to update the UI and avoid these data inconsistency bugs.&lt;/p&gt;

&lt;p&gt;Lastly, you can install the &lt;a href="https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd?hl=en" rel="noopener noreferrer"&gt;Redux DevTools&lt;/a&gt; that give you insights into your application’s current state to simplify debugging or testing your application. It’s a great incentive to get started with Redux.&lt;/p&gt;

&lt;p&gt;Next, let’s explore Redux with code examples.&lt;/p&gt;
&lt;h2&gt;
  
  
  Redux with code examples - How does it work?
&lt;/h2&gt;

&lt;p&gt;Let’s recap the Redux cycle before we take a look at our code example. This is how the Redux cycle looks like:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Users interact with the interface and triggers an action&lt;/li&gt;
&lt;li&gt;Action with/without payload is sent to a reducer using the dispatcher&lt;/li&gt;
&lt;li&gt;Reducer checks if it handles the action and produces a new state based on the action and its payload&lt;/li&gt;
&lt;li&gt;State changes are notified via subscription methods&lt;/li&gt;
&lt;li&gt;UI renders again based on state changes received via the subscription method&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, let’s explore how this works using code. We’ll create a simple webpage that allows you to increase or decrease a counter in the state using plus and minus buttons. We’ll use a single &lt;code&gt;index.html&lt;/code&gt; document that contains a script tag with all the necessary code. &lt;/p&gt;

&lt;p&gt;You can find the completed code via &lt;a href="https://codesandbox.io/s/redux-fundamentals-core-example-forked-nigo3?file=/index.html" rel="noopener noreferrer"&gt;CodeSandbox.io&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 1: Exploring index.html
&lt;/h3&gt;

&lt;p&gt;First, let’s create an &lt;code&gt;index.html&lt;/code&gt; document with the following HTML setup. This will render the current counter value and buttons to increase or decrease the counter.&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="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Redux basic example&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://unpkg.com/redux@latest/dist/redux.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
        Counter: &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"count"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;0&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"increment"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;+&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"decrement"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;-&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, let's take a look at how we can define actions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Define Redux actions
&lt;/h3&gt;

&lt;p&gt;Let’s define actions we want to dispatch to the reducer when the user clicks the increase or decrease button. &lt;/p&gt;

&lt;p&gt;We can listen for the &lt;code&gt;click&lt;/code&gt; event and dispatch a new action to the Redux store, which contains the reducer. &lt;/p&gt;

&lt;p&gt;Make sure to dispatch an object that contains the &lt;code&gt;type&lt;/code&gt; property. This property contains the name of the action. As a best practice, use the format &lt;code&gt;&amp;lt;reducer-name&amp;gt;/&amp;lt;action&amp;gt;&lt;/code&gt;. This makes it easier to identify actions as multiple components can send the same action. In our example, we will name the reducer &lt;code&gt;counter&lt;/code&gt;. Therefore, we get the following actions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;counter/increment&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;counter/decrement&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&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;script&amp;gt;&lt;/span&gt;
      &lt;span class="nb"&gt;document&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;increment&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="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;counter/increment&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="nb"&gt;document&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;decrement&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="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;counter/decrement&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="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, let’s define the reducer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Define a reducer
&lt;/h3&gt;

&lt;p&gt;As we can dispatch multiple actions to the reducer, we’ll use a switch statement to handle the different actions.&lt;/p&gt;

&lt;p&gt;First, we define the initial state for the application by setting the &lt;code&gt;count&lt;/code&gt; equal to zero. Next, we define a &lt;code&gt;counterReducer&lt;/code&gt; function that accepts the current state and the dispatched action. &lt;/p&gt;

&lt;p&gt;Two scenarios are possible here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reducer receives an &lt;code&gt;counter/increment&lt;/code&gt; action to increase the counter&lt;/li&gt;
&lt;li&gt;Reducer receives an &lt;code&gt;counter/decrement&lt;/code&gt; action to decrease the counter&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Note that we use the reducer function as an argument for the &lt;code&gt;createStore&lt;/code&gt; function to define a new Redux store for our application.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
      &lt;span class="c1"&gt;// Define an initial state for the app&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;count&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="c1"&gt;// Create a "reducer" function that determines what the new state&lt;/span&gt;
      &lt;span class="c1"&gt;// should be when something happens in the app&lt;/span&gt;
      &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;counterReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;counter/increment&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&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="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;counter/decrement&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&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="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;// If the reducer doesn't care about this action type,&lt;/span&gt;
            &lt;span class="c1"&gt;// return the existing state unchanged&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; Don’t forget to add a &lt;code&gt;default&lt;/code&gt; clause to your &lt;code&gt;switch&lt;/code&gt; statement that returns the current state. You may have multiple reducers for your application. When you dispatch an action, the action is sent to all reducers and not only the intended one. Therefore, you want all reducers to return the current state to avoid errors and only the intended reducer to return the updated state.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Subscribing to state changes
&lt;/h3&gt;

&lt;p&gt;In this step, we want to subscribe to state changes to update the UI when the state has changed.&lt;/p&gt;

&lt;p&gt;We define a &lt;code&gt;render&lt;/code&gt; method that retrieves the current state and renders the &lt;code&gt;count&lt;/code&gt; property. Further, we pass this &lt;code&gt;render&lt;/code&gt; function as an argument to the &lt;code&gt;store.subscribe&lt;/code&gt; method to update the UI automatically when the state changes. This method exposed by our newly created store will call the &lt;code&gt;render&lt;/code&gt; function when the state has changed.&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;script&amp;gt;&lt;/span&gt;
      &lt;span class="c1"&gt;// Our "user interface" is some text in a single HTML element&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;countEl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;count&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="c1"&gt;// Whenever the store state changes, update the UI by&lt;/span&gt;
      &lt;span class="c1"&gt;// reading the latest store state and showing new data&lt;/span&gt;
      &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;render&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;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;countEl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="c1"&gt;// Update the UI with the initial data&lt;/span&gt;
      &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

      &lt;span class="c1"&gt;// And subscribe to redraw whenever the data changes in the future&lt;/span&gt;
      &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure to take a look at the &lt;a href="https://codesandbox.io/s/redux-fundamentals-core-example-forked-nigo3?file=/index.html" rel="noopener noreferrer"&gt;completed code&lt;/a&gt;. You can use the CodeSandbox to play with the code yourself or fork the example.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Completed code below:&lt;/b&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Redux basic example&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://unpkg.com/redux@latest/dist/redux.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
        Counter: &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"count"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;0&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"increment"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;+&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"decrement"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;-&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;count&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="nf"&gt;counterReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;counter/increment&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&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="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;counter/decrement&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&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="nl"&gt;default&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;state&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Redux&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;counterReducer&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;countEl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;count&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;render&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;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;countEl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

      &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nb"&gt;document&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;increment&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="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;counter/increment&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="nb"&gt;document&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;decrement&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="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;counter/decrement&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="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it!&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the benefits of using Redux?
&lt;/h2&gt;

&lt;p&gt;There are many benefits to using Redux. The most prominent benefit is improved state management for your application. Yet, there are many other benefits.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Easy debugging and testing.&lt;/strong&gt; You can use the &lt;a href="https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd?hl=en" rel="noopener noreferrer"&gt;Redux DevTools&lt;/a&gt; or log the state to understand better what’s happening in your application. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reducer functions can be tested quickly.&lt;/strong&gt;  As reducer functions are pure functions, they produce the same output for the same input. Therefore, testing pure functions become a simple task.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hook monitoring tools.&lt;/strong&gt; You can hook monitoring tools to your application’s state to monitor the state in real-time. This improves visibility for your application and allows you to track different metrics.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Predictable outcome.&lt;/strong&gt; Every action produces a predictable outcome. Your state store acts as a single source of truth. Therefore, you can avoid data inconsistency bugs and don’t have to worry about data synchronization issues between components.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  When not to choose Redux?
&lt;/h2&gt;

&lt;p&gt;For beginners, it’s an obvious choice to opt for Redux. Yet, you don’t always need Redux to manage the state of your application. &lt;/p&gt;

&lt;p&gt;Applications that consist of mostly simple UI changes most often don’t require a complicated pattern like Redux. Sometimes, old-fashioned state sharing between different components works as well and improves the maintainability of your code. &lt;/p&gt;

&lt;p&gt;Also, you can avoid using Redux if your data comes from a single data source per view. In other words, if you don’t require data from multiple sources, there’s no need to introduce Redux. Why? You won’t run into data inconsistency problems when accessing a single data source per view.&lt;/p&gt;

&lt;p&gt;Therefore, make sure to check if you need Redux before introducing its complexity. Although it’s a reasonably efficient pattern that promotes pure functions, it might be an overhead for simple applications that involve only a couple of UI changes. On top of that, don't forget that Redux is an in-memory state store. In other words, if your application crashes, you lose your entire application state. This means that you have to use a caching solution to create a backup of your application state, which again creates extra overhead.&lt;/p&gt;

&lt;p&gt;If you want to learn more about Redux, check out the &lt;a href="https://redux.js.org/faq" rel="noopener noreferrer"&gt;Redux FAQ&lt;/a&gt; section, which contains tons of interesting questions you might have about Redux. Also, check out this amazing &lt;a href="https://www.youtube.com/watch?v=np8A_aW7Pew&amp;amp;ab_channel=HiteshChoudhary" rel="noopener noreferrer"&gt;analogy for Redux&lt;/a&gt; by Hitesh Choudhary.&lt;/p&gt;

</description>
      <category>redux</category>
      <category>react</category>
      <category>vue</category>
      <category>angular</category>
    </item>
    <item>
      <title>Instagram Automation Bot for JavaScript: How to use InstAuto?</title>
      <dc:creator>Michiel Mulders</dc:creator>
      <pubDate>Thu, 19 Nov 2020 14:27:45 +0000</pubDate>
      <link>https://dev.to/michielmulders/instagram-automation-bot-for-javascript-how-to-use-instauto-2240</link>
      <guid>https://dev.to/michielmulders/instagram-automation-bot-for-javascript-how-to-use-instauto-2240</guid>
      <description>&lt;p&gt;For many Instagram users, using an Instagram automation bot has proven to grow their account and audience.&lt;/p&gt;

&lt;p&gt;An Instagram bot provides a simple way to find new accounts to follow, which are likely interested in your post's content. &lt;/p&gt;

&lt;p&gt;However, we must use an Instagram bot correctly. There's no point in targeting people who like content about cars while posting content about flowers. &lt;/p&gt;

&lt;p&gt;On top of that, Instagram implements stringent guidelines for bot automation. Although we don't know the exact limitations, a study by SocialPros.co showed the following average interaction statistics for users in 2020:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;13 follows per hour, or &lt;strong&gt;100-150 follows per day&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;300 to 400 likes per day&lt;/strong&gt; (of followed accounts)&lt;/li&gt;
&lt;li&gt;2 to 5 comments per hour, or &lt;strong&gt;20-30 comments per day&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this article, we'll learn how to set up the JavaScript Instagram automation bot &lt;a href="https://github.com/mifi/instauto"&gt;InstAuto&lt;/a&gt; and how to automate within Instagram's terms of service without receiving a &lt;a href="https://blog.hubspot.com/marketing/instagram-shadowban"&gt;shadowban&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why use an Instagram bot?
&lt;/h1&gt;

&lt;p&gt;Instagram bots help us with repetitive tasks, such as liking, commenting, and (un)following. These are the core actions of the Instagram platform and consume a lot of time when done manually.&lt;/p&gt;

&lt;p&gt;Therefore, this presents us with the opportunity to use an &lt;a href="https://blog.kicksta.co/time-saving-instagram-automation-tools/"&gt;Instagram automation&lt;/a&gt; bot to automate the above tasks.&lt;/p&gt;

&lt;p&gt;On top of that, an Instagram bot offers us much more flexibility. &lt;/p&gt;

&lt;p&gt;Let's say we follow five new accounts, and we want to unfollow them after three days. It's quite a daunting task to manually verify if this person has followed you and then unfollow him. &lt;/p&gt;

&lt;p&gt;For this reason, we use an Instagram bot as it allows for much more complex scenarios. Therefore, an Instagram automation bot often keeps track of likes, follows, and comments using a database. A database allows the bot to quickly lookup accounts that we followed three days ago, which we want to unfollow.&lt;/p&gt;

&lt;p&gt;Let's take a look at how we can use InstAuto to configure our first Instagram automation bot.&lt;/p&gt;

&lt;h1&gt;
  
  
  Requirements
&lt;/h1&gt;

&lt;p&gt;First, let's discuss the requirements for this tutorial.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://nodejs.org/en/"&gt;Node.js&lt;/a&gt; version 8 or newer&lt;/li&gt;
&lt;li&gt;New project setup using &lt;code&gt;npm init&lt;/code&gt; with an &lt;code&gt;index.js&lt;/code&gt; file in the root&lt;/li&gt;
&lt;li&gt;Install required dependencies: &lt;code&gt;npm install --save dotenv puppeteer instauto&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Done? Let's continue!&lt;/p&gt;

&lt;h1&gt;
  
  
  Step 1: Creating Your First Instagram Automation Bot
&lt;/h1&gt;

&lt;p&gt;It's time to modify the &lt;code&gt;index.js&lt;/code&gt; file. We first want to load the required dependencies. We'll use &lt;code&gt;dotenv&lt;/code&gt; to hide secrets, such as our Instagram username and password, where we use &lt;code&gt;puppeteer&lt;/code&gt; for controlling a Chrome or Chromium browser instance to automate all aspects of our Instagram tasks. &lt;/p&gt;

&lt;p&gt;Add the following code.&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="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;config&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;puppeteer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;puppeteer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Instauto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;instauto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, let's prepare the &lt;code&gt;options&lt;/code&gt; object to configure our Instagram bot. Here, we can configure the limits for our Instagram bot. To be safe, we only allow 20 new follows per hour and limit the total number of followers per day to 150. Also, we set a maximum number of likes per day equal to 50. &lt;/p&gt;

&lt;p&gt;Note that you toggle a dry run on or off. For testing purposes, enable the &lt;code&gt;dryRun&lt;/code&gt; property.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;cookiesPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./cookies.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;INSTA_USERNAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;INSTA_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="c1"&gt;// Global limit that prevents follow or unfollows (total) to exceed this number over a sliding window of one hour:&lt;/span&gt;
  &lt;span class="na"&gt;maxFollowsPerHour&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// Global limit that prevents follow or unfollows (total) to exceed this number over a sliding window of one day:&lt;/span&gt;
  &lt;span class="na"&gt;maxFollowsPerDay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// (NOTE setting the above parameters too high will cause temp ban/throttle)&lt;/span&gt;

  &lt;span class="na"&gt;maxLikesPerDay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;


  &lt;span class="na"&gt;dontUnfollowUntilTimeElapsed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="c1"&gt;// Usernames that we should not touch, e.g. your friends and actual followings&lt;/span&gt;
  &lt;span class="na"&gt;excludeUsers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;

  &lt;span class="c1"&gt;// If true, will not do any actions (defaults to true)&lt;/span&gt;
  &lt;span class="na"&gt;dryRun&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we need to add our Instagram username and password. As you can see, we import those secrets using &lt;code&gt;process.env&lt;/code&gt; (&lt;a href="https://www.npmjs.com/package/dotenv"&gt;dotenv via npm&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Therefore, let's create a &lt;code&gt;.env&lt;/code&gt; file in the root of your project. Make sure to add both &lt;code&gt;INSTA_USERNAME&lt;/code&gt; and &lt;code&gt;INSTA_PASSWORD&lt;/code&gt; variables.&lt;/p&gt;

&lt;p&gt;Here's an example of the &lt;code&gt;.env&lt;/code&gt; file. Make sure to replace the values!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INSTA_USERNAME=myusername
INSTA_PASSWORD=mypassword
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All good? Let's add the bot execution code. This snippet follows the code for the &lt;code&gt;options&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;Here, we launch an instance of Puppeteer to enable automatization. Next, we also create a database that keeps track of followed and unfollowed users, and liked photos.&lt;/p&gt;

&lt;p&gt;Then, we pass the Puppeteer browser instance, database, and options object to the &lt;code&gt;InstAuto&lt;/code&gt; dependency to create our bot.&lt;/p&gt;

&lt;p&gt;It's possible to pass one or multiple users for which we want to follow their followers. At the moment, we've added only one Instagram username &lt;a href="https://www.instagram.com/dedik_armawann/"&gt;&lt;code&gt;dedik_armawann&lt;/code&gt;&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is the current setup for the bot:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Follow all users (within the predefined limits) for user &lt;code&gt;dedik_armawann&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Skip all private accounts&lt;/li&gt;
&lt;li&gt;Like 1-2 user images&lt;/li&gt;
&lt;li&gt;When the bot has completed following all accounts, it will sleep for 10 minutes and start the unfollow process for accounts that haven't followed us back. Remember that we've set the &lt;code&gt;dontUnfollowUntilTimeElapsed&lt;/code&gt; to three days.&lt;/li&gt;
&lt;li&gt;Unfollow all users that didn't follow us back after 60 days (clean up phase)
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;browser&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="nx"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;puppeteer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;headless&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Create a database where state will be loaded/saved to&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;instautoDb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Instauto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;JSONDB&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="c1"&gt;// Will store a list of all users that have been followed before, to prevent future re-following.&lt;/span&gt;
      &lt;span class="na"&gt;followedDbPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./followed.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="c1"&gt;// Will store all unfollowed users here&lt;/span&gt;
      &lt;span class="na"&gt;unfollowedDbPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./unfollowed.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="c1"&gt;// Will store all likes here&lt;/span&gt;
      &lt;span class="na"&gt;likedPhotosDbPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./liked-photos.json&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;instauto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Instauto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;instautoDb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// List of usernames that we should follow the followers of, can be celebrities etc.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;usersToFollowFollowersOf&lt;/span&gt; &lt;span class="o"&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;dedik_armawann&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="c1"&gt;// Now go through each of these and follow a certain amount of their followers&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;instauto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;followUsersFollowers&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;usersToFollowFollowersOf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;skipPrivate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;enableLikeImages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;instauto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&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="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// This is used to unfollow people - auto-followed AND manually followed -&lt;/span&gt;
    &lt;span class="c1"&gt;// who are not following us back, after some time has passed&lt;/span&gt;
    &lt;span class="c1"&gt;// (config parameter dontUnfollowUntilTimeElapsed)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;instauto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unfollowNonMutualFollowers&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;instauto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&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="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Unfollow auto-followed users (regardless of whether they are following us)&lt;/span&gt;
    &lt;span class="c1"&gt;// after a certain amount of days&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;instauto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unfollowOldFollowed&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;ageInDays&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Done running&lt;/span&gt;&lt;span class="dl"&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;instauto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30000&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&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;finally&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Closing browser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;browser&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;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Good, let's try our bot!&lt;/p&gt;

&lt;h1&gt;
  
  
  Step 3: Starting a Bot Dry Run
&lt;/h1&gt;

&lt;p&gt;Now, let's start an Instagram bot dry run. We can execute the &lt;code&gt;index.js&lt;/code&gt; file from our terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we've passed the correct Instagram username and password, the bot will open a new Chromium browser and log in to your Instagram account. &lt;/p&gt;

&lt;p&gt;Have some patients while the bot is running. The bot will eventually look up the usernames we've passed to follow and start the follow and liking process. &lt;/p&gt;

&lt;p&gt;We can always track the progress in the terminal as the bot prints everything it does. On top of that, you can also open the following files to track the progress:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;followed.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;unfollowed.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;liked-photos.json&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's an example of how the bot works:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/NjJgpXiyO0Y"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Does your bot work? Yes! Next, let's customize our bot.&lt;/p&gt;

&lt;h1&gt;
  
  
  Step 4: Instagram Bot Customization
&lt;/h1&gt;

&lt;p&gt;In this step, we want to discuss different parameters to tailor your bot. Let's discuss four essential parameters.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;followUserRatioMin&lt;/code&gt;: Don't follow users that have a follower to following ratio of less than the defined value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;followUserRatioMax&lt;/code&gt;: Don't follow users that have a follower to following ratio higher than the defined value. Often, spam accounts have a very high ratio. To avoid those accounts, you can set this property.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;followUserMaxFollowers&lt;/code&gt;: Don't follow users who have more followers than the defined value. This property is useful to avoid popular accounts as they often don't follow back. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;followUserMaxFollowing&lt;/code&gt;: Similar property to not follow users who have more people following them than the defined value.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Of course, you can always exclude certain users from your bot using the &lt;code&gt;excludeUsers&lt;/code&gt; array property.&lt;/p&gt;

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

&lt;p&gt;In this article, we've learned how to set up an Instagram automation bot, operate a bot within the Instagram terms of service, and customize the InstAuto bot.&lt;/p&gt;

&lt;p&gt;Tip: Don't forget to set the &lt;code&gt;dryRun&lt;/code&gt; property to &lt;code&gt;false&lt;/code&gt; when using the bot in &lt;strong&gt;production&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You can find more information about the bot on &lt;a href="https://github.com/mifi/instauto"&gt;GitHub&lt;/a&gt; and more information about running the &lt;a href="https://github.com/mifi/instauto#running-with-pm2"&gt;bot on a server&lt;/a&gt; using a tool such as &lt;code&gt;pm2&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>instagram</category>
    </item>
    <item>
      <title>Creating Custom Blockchain Transactions with the SDK — Introducing Lisk Bills</title>
      <dc:creator>Michiel Mulders</dc:creator>
      <pubDate>Thu, 22 Aug 2019 14:28:03 +0000</pubDate>
      <link>https://dev.to/michielmulders/creating-custom-blockchain-transactions-with-the-sdk-introducing-lisk-bills-bf1</link>
      <guid>https://dev.to/michielmulders/creating-custom-blockchain-transactions-with-the-sdk-introducing-lisk-bills-bf1</guid>
      <description>&lt;p&gt;The &lt;a href="https://www.youtube.com/watch?v=NYfUBXw4Tw0" rel="noopener noreferrer"&gt;Lisk Bills webinar&lt;/a&gt; is now live on our &lt;a href="https://www.youtube.com/channel/UCuqpGfg_bOQ8Ja4pj811PWg" rel="noopener noreferrer"&gt;YouTube channel&lt;/a&gt;. Subscribe for more educational developer content.&lt;/p&gt;

&lt;p&gt;Lisk’s Alpha SDK Phase officially began in late July with the release of SDK 2.1.0. We decided what better way to showcase the potential of custom transactions than to create our own proof-of-concept (PoC) blockchain application. To explore the possibilities of custom transactions at their best, we decided to build an invoicing application and through this register two new custom transactions on our blockchain.&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction to Custom Transactions
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://lisk.io/sdk" rel="noopener noreferrer"&gt;Lisk SDK&lt;/a&gt; allows you to define your own custom transaction types where you can implement the required logic for your blockchain use-case. The custom transaction types are an extension to the default set of transactions that is already part of the Lisk Protocol. You can read more about the predefined types &lt;a href="https://lisk.io/documentation/lisk-sdk/customize" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The beginning of the Alpha SDK phase of our &lt;a href="https://lisk.io/roadmap" rel="noopener noreferrer"&gt;roadmap&lt;/a&gt; allows you to create your own proof-of-concept blockchain applications aligned with our architecture. This phase of our roadmap also allows us to get feedback on how the development experience can be improved via discussion on &lt;a href="https://discordapp.com/channels/405002561775599619/405002561779793921" rel="noopener noreferrer"&gt;our community channels&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Custom Transactions to Grow the Lisk Ecosystem
&lt;/h1&gt;

&lt;p&gt;Custom transactions offer great business value to the Lisk Ecosystem as they allow for a lot of creativity. We believe custom transactions are the “creative spark” for the Lisk Ecosystem to see a whole bunch of innovative projects being created. &lt;strong&gt;We already see community members coming up with their own solutions ranging from hardware-utilizing rental bike tracking system, &lt;a href="https://sites.google.com/view/liskbike" rel="noopener noreferrer"&gt;Lisk.Bike&lt;/a&gt;, to the usage of our modular JavaScript library for an innovative take on a classic strategy game, &lt;a href="https://sidechainsolutions.io/articles/lisk-tictactoe" rel="noopener noreferrer"&gt;Lisk Tic-Tac-Toe&lt;/a&gt;.&lt;/strong&gt; Now is your time to get creative!&lt;/p&gt;

&lt;h1&gt;
  
  
  Benefits of Custom Transactions
&lt;/h1&gt;

&lt;p&gt;Every account object has the ability to store data in its &lt;code&gt;asset&lt;/code&gt; field. Custom transactions make clever use of this. The use of the &lt;code&gt;asset&lt;/code&gt; field allows for any type of stringified data to be passed to the transaction. This allows for greater flexibility and creativity when defining custom logic.&lt;/p&gt;

&lt;p&gt;Besides that, every custom transaction can access and modify all account-related data and only read transaction-related data from the database. This allows for more advanced interactions between data and even between different custom transactions. For example, our PoC used the data from the &lt;em&gt;Invoice&lt;/em&gt; transaction to verify the validity of the &lt;em&gt;Payment&lt;/em&gt; transaction.&lt;/p&gt;

&lt;p&gt;You can also create a token in the asset field with some basic transfer and verification logic. In the end, this is just another way of smart contract logic.&lt;/p&gt;

&lt;p&gt;Let’s continue with exploring the technicals of our Lisk Bills PoC.&lt;/p&gt;

&lt;h1&gt;
  
  
  Lisk Bills — Blockchain-Based Invoicing
&lt;/h1&gt;

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

&lt;p&gt;As we like the &lt;em&gt;Keep it Simple and Stupid (KISS)&lt;/em&gt; approach, we have built a minimal frontend with React that uses the Lisk Alpha SDK to interact directly with your blockchain application. The PoC includes two actors, the client and the freelancer.&lt;/p&gt;

&lt;p&gt;Imagine Alice (Freelancer) and Bob (Client). Bob is looking for a new logo for his website and decides to consult a freelancer. While looking for a good designer, he comes across Alice who offers some spectacular designs in her portfolio. Bob is so excited he decides to immediately employ Alice’s skillset.&lt;/p&gt;

&lt;p&gt;A few days go by, and Alice returns the promised logo together with an invoice. &lt;strong&gt;However, Bob is a big fan of blockchain technology as it helps to ease the settlement process. It often happens parties disagree about the agreed price, product, or even shipping terms. Bob, therefore, believes blockchain can help with recording all this information right from the beginning, so no disputes can occur and human error can be eliminated. The blockchain should act as proof for the invoice.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For the above reason, Bob asks Alice to create the invoice via a Lisk custom transaction.&lt;/p&gt;

&lt;p&gt;In order to do so, Alice first has to log in with her passphrase to the Lisk Bills application.&lt;/p&gt;

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

&lt;h1&gt;
  
  
  Custom Transaction 1: Invoice
&lt;/h1&gt;

&lt;p&gt;Now Alice has been logged in, she can create an invoice. To create the custom invoice transaction, Alice has to input the following details:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Client&lt;/code&gt; holds Bob’s Lisk address or business name.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RequestedAmount&lt;/code&gt; holds the amount Bob is due to Alice.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Description&lt;/code&gt; to describe the delivered design service.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;The following data is stored in the asset field of the transaction. As this is a normal &lt;em&gt;BaseTransaction&lt;/em&gt;, we can simply specify Bob’s Lisk address as the recipient for the transaction.&lt;/p&gt;

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

&lt;p&gt;Before we dive into the technicals, make sure to &lt;strong&gt;open or clone the &lt;a href="https://github.com/LiskHQ/lisk-sdk-examples/tree/development/invoice" rel="noopener noreferrer"&gt;lisk-sdk-examples repository&lt;/a&gt;&lt;/strong&gt;. The code for both custom transactions can be found in &lt;em&gt;&lt;a href="https://github.com/LiskHQ/lisk-sdk-examples/blob/development/invoice/transactions/invoice_transaction.js" rel="noopener noreferrer"&gt;invoice/transactions/invoice_transaction.js&lt;/a&gt;&lt;/em&gt; and &lt;em&gt;&lt;a href="https://github.com/LiskHQ/lisk-sdk-examples/blob/development/invoice/transactions/payment_transaction.js" rel="noopener noreferrer"&gt;invoice/transactions/payment_transaction.js&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Technicals
&lt;/h1&gt;

&lt;p&gt;First of all, let’s take a look at the class definition. The &lt;code&gt;InvoiceTransaction&lt;/code&gt; extends the &lt;code&gt;BaseTransaction&lt;/code&gt; which means it’s inheriting its properties. As the name suggests, &lt;code&gt;BaseTransaction&lt;/code&gt; is the most basic interface for creating new transaction types. Other transaction types also exist in the system, later we will show an example of extending the &lt;code&gt;TransferTransaction&lt;/code&gt; type.&lt;/p&gt;

&lt;p&gt;When extending the &lt;code&gt;BaseTransaction&lt;/code&gt; we can provide extra business logic for the following methods: &lt;em&gt;Prepare, Validate Asset, Apply Asset and Undo Asset&lt;/em&gt;. You can find out more about these &lt;a href="https://github.com/LiskHQ/lisk-docs/blob/master/lisk-sdk/customize.md#prepare" rel="noopener noreferrer"&gt;methods in our documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also, pay attention to the static getter function for retrieving the type of the transaction. As an example, we have chosen &lt;code&gt;13&lt;/code&gt; to be the type number for this transaction. Besides that, you can set the fee you want users to pay for using this transaction type. For now, we have set this to 1 LSK (10 to the 8th beddows).&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InvoiceTransaction&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseTransaction&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nc"&gt;TYPE &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="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nc"&gt;FEE &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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;8&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="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;h2&gt;
  
  
  Prepare
&lt;/h2&gt;

&lt;p&gt;The prepare function is responsible for loading the required data used inside the &lt;code&gt;applyAsset()&lt;/code&gt; and &lt;code&gt;undoAsset()&lt;/code&gt; function. Here, we try to load the account data for the sender as we want to add data to his asset field in the &lt;code&gt;applyAsset()&lt;/code&gt; function. This data will be loaded from the &lt;em&gt;StateStore&lt;/em&gt; object that provides access to data in the database.&lt;/p&gt;

&lt;p&gt;We can cache the sender account like this by passing an array with filters.&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;await&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;senderId&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;However, we actually don’t have to manually cache the data. We can simply call the parent method for the &lt;code&gt;prepare&lt;/code&gt; function in the &lt;a href="https://github.com/LiskHQ/lisk-sdk/blob/development/elements/lisk-transactions/src/base_transaction.ts" rel="noopener noreferrer"&gt;abstract &lt;code&gt;BaseTransaction&lt;/code&gt; class&lt;/a&gt; which will by default cache the sender account to &lt;a href="https://github.com/LiskHQ/lisk-sdk/blob/development/elements/lisk-transactions/src/base_transaction.ts#L348" rel="noopener noreferrer"&gt;deduct the fee in the apply step&lt;/a&gt;.&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;async&lt;/span&gt; &lt;span class="nf"&gt;prepare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prepare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Validate Asset
&lt;/h2&gt;

&lt;p&gt;Before a transaction reaches the apply step it gets validated. Check the transaction’s asset correctness from the schema perspective (no access to &lt;code&gt;StateStore&lt;/code&gt; here). You can invalidate the transaction by pushing an error into the result array.&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="nf"&gt;validateAsset&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;errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&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="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TransactionError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Invalid "asset.client" defined on transaction&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.asset.client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;A string value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;requestedAmount&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;requestedAmount&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&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="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TransactionError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Invalid "asset.requestedAmount" defined on transaction&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.asset.requestedAmount&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;requestedAmount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;A string value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&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="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TransactionError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Invalid "asset.description" defined on transaction&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.asset.description&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;A string value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Apply Asset
&lt;/h2&gt;

&lt;p&gt;As you can see, we finally use the loaded account which we put in the store during the &lt;code&gt;prepare&lt;/code&gt; step. Next, we update the invoice count and record the ID of the invoice in an array with sent invoices. We will use this data in our frontend to display all invoices.&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="nf"&gt;applyAsset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;store&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;sender&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;senderId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Save invoice count and IDs&lt;/span&gt;
    &lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;invoiceCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;invoiceCount&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;undefined&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="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;invoiceCount&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;invoicesSent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;invoicesSent&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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;sender&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;invoicesSent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sender&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;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Undo Asset
&lt;/h2&gt;

&lt;p&gt;Do not underestimate the importance of the &lt;code&gt;undoAsset()&lt;/code&gt; function. The &lt;em&gt;Undo&lt;/em&gt; function allows us to rollback to a previous blockchain state. Therefore, we should exactly tell our blockchain application how it should roll back changes.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;Undo&lt;/em&gt; function is of most importance for the fork recovery mechanism. In case a fork occurs on a chain with tip B and we want to roll back to a common height in order to re-apply blocks up to the tip of chain A, we need the &lt;em&gt;Undo&lt;/em&gt; function to do the actual rollback to this common height.&lt;/p&gt;

&lt;p&gt;For the invoice proof of concept, the code reduces the &lt;code&gt;invoiceCount&lt;/code&gt; and removed the invoice ID from the &lt;code&gt;invoicesSent&lt;/code&gt; array.&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="nf"&gt;undoAsset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;store&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;sender&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;senderId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Rollback invoice count and IDs&lt;/span&gt;
    &lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;invoiceCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;invoiceCount&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="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;invoiceCount&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;invoicesSent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;invoicesSent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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="kc"&gt;undefined&lt;/span&gt; 
        &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;invoicesSent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;invoicesSent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sender&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;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, we have explored the functions for the invoice transaction. Let’s move to the payment transaction.&lt;/p&gt;

&lt;h1&gt;
  
  
  Custom Transaction 2: Payment
&lt;/h1&gt;

&lt;p&gt;Now Bob has received the Invoice Transaction in his wallet, he decides to pay for the invoice. In order to fulfill the transaction, we would normally send a &lt;code&gt;TransferTransaction&lt;/code&gt; which is natively supported by Lisk SDK.&lt;/p&gt;

&lt;p&gt;However, doing so would make this a very boring tutorial. Therefore, Bob decides to use another custom transaction to showcase Lisk’s possibilities. This custom Payment Transaction holds logic to verify the transferred amount is at least equal to the &lt;code&gt;RequestedAmount&lt;/code&gt;. Also, the transaction requires Bob to specify the ID of the invoice he wants to fulfill.&lt;/p&gt;

&lt;p&gt;If the transferred amount is too low or the invoice ID just doesn’t exist, the transaction fails. Bob keeps his side of the agreement and sends the requested amount to Alice’s invoice ID. Bob even adds a tip for Alice’s great work.&lt;/p&gt;

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

&lt;p&gt;This is how the UI implementation looks like for paying an invoice with our Lisk Bills application.&lt;/p&gt;

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

&lt;h1&gt;
  
  
  Technicals
&lt;/h1&gt;

&lt;p&gt;Again, let’s take a look at the class definition. The &lt;code&gt;PaymentTransaction&lt;/code&gt; extends the &lt;code&gt;TransferTransaction&lt;/code&gt; which means it’s inheriting its properties like a different fee and transfer-related verification checks. Also, pay attention to the static getter function for retrieving the type of the transaction. As we can not have identical transaction types, the &lt;code&gt;PaymentTransaction&lt;/code&gt; has received type &lt;code&gt;14&lt;/code&gt;.&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PaymentTransaction&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;TransferTransaction&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nc"&gt;TYPE &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="mi"&gt;14&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;Also, note we don’t define a static getter function for &lt;code&gt;FEE&lt;/code&gt;. We didn’t implement it here as we don’t want to overwrite the &lt;code&gt;FEE&lt;/code&gt; defined in the &lt;code&gt;TransferTransaction&lt;/code&gt;. In short, we want to use the &lt;code&gt;0.1&lt;/code&gt; fee defined in &lt;code&gt;TransferTransaction&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prepare
&lt;/h2&gt;

&lt;p&gt;The prepare function is responsible for loading the required data into the store to be used inside the &lt;code&gt;applyAsset()&lt;/code&gt; and &lt;code&gt;undoAsset()&lt;/code&gt; function. For the &lt;code&gt;PaymentTransaction&lt;/code&gt;, we are loading the transaction that holds the invoice using the &lt;code&gt;ID&lt;/code&gt; sent with &lt;code&gt;this.asset.data&lt;/code&gt;.&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;async&lt;/span&gt; &lt;span class="nf"&gt;prepare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prepare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;store&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;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Validate Asset
&lt;/h2&gt;

&lt;p&gt;As you might have noticed, we didn’t implement the &lt;code&gt;validateAsset()&lt;/code&gt; function for the payment transaction. The only check we have to perform is validating if the sent number of tokens is at least equal to the requested number of tokens.&lt;/p&gt;

&lt;p&gt;In order to validate this, we need access to the &lt;code&gt;StateStore&lt;/code&gt; as we need to cache the invoice transaction. Because we can only perform static checks in the &lt;code&gt;validateAsset()&lt;/code&gt; function that don’t use the &lt;code&gt;StateStore&lt;/code&gt;, this check is &lt;a href="https://github.com/LiskHQ/lisk-sdk-examples/blob/development/invoice/transactions/payment_transaction.js#L20" rel="noopener noreferrer"&gt;moved to the apply step&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Apply Asset
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;applyAsset()&lt;/code&gt; function first tries to find the corresponding invoice transaction. If this transaction exists, we further check for the number of tokens transferred is at least equal to the requested amount in the invoice. If this check succeeds, the transaction gets applied.&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="nf"&gt;applyAsset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;store&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;errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;applyAsset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;store&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;transaction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;transaction&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&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="c1"&gt;// Find related invoice in transactions for invoiceID&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;requestedAmount&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TransactionError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Paid amount is lower than amount stated on invoice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.amount&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nx"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;requestedAmount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Expected amount to be equal or greated than `requestedAmount`&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TransactionError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Invoice does not exist for ID&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.asset.invoiceID&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Existing invoiceID registered as invoice transaction&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Undo Asset
&lt;/h2&gt;

&lt;p&gt;No rollback logic is required for the undo step of the payment transaction. We do not modify any data in the store with the &lt;code&gt;set&lt;/code&gt; method, so no need for defining undo steps to revert this data change.&lt;/p&gt;

&lt;p&gt;However, do not forget to call &lt;code&gt;super.undoAsset(store)&lt;/code&gt; as the &lt;em&gt;Undo&lt;/em&gt; step will make sure the fee Alice has paid gets returned to her account’s balance.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to Register Custom Transactions?
&lt;/h1&gt;

&lt;p&gt;Ok, we have prepared both of our custom transactions. Bob and Alice are very happy to use both transactions in order to finalize their deal. However, we don’t know yet how to register these new transactions on our blockchain application.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/LiskHQ/lisk-sdk-examples/blob/development/invoice/index.js" rel="noopener noreferrer"&gt;invoice/index.js&lt;/a&gt; file holds the startup code for running your custom blockchain and also registers both transactions. It’s as simple as that!&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;genesisBlockDevnet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;configDevnet&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lisk-sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;InvoiceTransaction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PaymentTransaction&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./transactions/index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;genesisBlockDevnet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;configDevnet&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;registerTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;InvoiceTransaction&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;registerTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PaymentTransaction&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;App started...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Faced error in application&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&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;exit&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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, we are all done! At last, let’s take a brief look at the considerations regarding the use of custom transactions.&lt;/p&gt;

&lt;h1&gt;
  
  
  Considerations of Using Custom Transactions
&lt;/h1&gt;

&lt;p&gt;Currently, we expect users to run their own blockchain instance that registers their freshly created custom transaction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It took us a few weeks to build this prototype. We have deliberately kept it simple to act as a learning resource, and as inspiration for the community. It is not production-ready.&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;Lisk aims to allow for creativity within the blockchain industry by providing the ability to process data with custom business logic. This concept is very similar to smart contracts as they also hold custom business logic. We are pleased to introduce you to Lisk Bills as the first example of what is possible with our SDK.&lt;/p&gt;

&lt;p&gt;We hope this freedom will spark a whole bunch of new innovative blockchain applications build on top of Lisk using the newly released Lisk Alpha SDK. Currently, we do not plan to support custom transactions on the Lisk mainnet but they are intended to be used inside your own blockchain application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lisk is on a mission to enable you to create decentralized, efficient, and transparent blockchain applications. Join us:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://discord.gg/GA9DZmt" rel="noopener noreferrer"&gt;Lisk Discord&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://lisk.io/sdk" rel="noopener noreferrer"&gt;SDK Page and Newsletter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://research.lisk.io/" rel="noopener noreferrer"&gt;Lisk Research&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/LiskHQ" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>blockchain</category>
      <category>javascript</category>
      <category>node</category>
    </item>
    <item>
      <title>Why we stopped using 'npm start' for running our blockchain core's child processes</title>
      <dc:creator>Michiel Mulders</dc:creator>
      <pubDate>Thu, 23 May 2019 15:52:18 +0000</pubDate>
      <link>https://dev.to/michielmulders/why-we-stopped-using-npm-start-for-running-our-blockchain-core-s-child-processes-1ef4</link>
      <guid>https://dev.to/michielmulders/why-we-stopped-using-npm-start-for-running-our-blockchain-core-s-child-processes-1ef4</guid>
      <description>&lt;p&gt;You shouldn't start applications through npm when you have child processes natively supported by Node.js. In this article, we will provide a list of best practices for Node.js applications with a code snippet that outlines the core problem and shows you how to reproduce the issue in 3 steps. In short, we stopped using npm start to run our blockchain's core and instead opted for using the native node command.&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction to npm and its most well-known command 'npm start'.
&lt;/h1&gt;

&lt;p&gt;Npm is the go-to node package manager when you are working on a JavaScript project. It allows you to install other people's code packages into your own project so you don't have to code everything you need from scratch. Npm also became famous because of its industry-wide usage of script commands that can be entered in the shell to start your application. Of course, the most well-known command is &lt;code&gt;npm start&lt;/code&gt; that acts as a wrapper for &lt;code&gt;node app.js&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Our challenge: npm runs app.js files as a child process ofnpm.
&lt;/h1&gt;

&lt;p&gt;However, what many don't know is that while using &lt;code&gt;npm start&lt;/code&gt; to trigger node app.js, &lt;strong&gt;npm is actually running your app.js file as a child process of npm which manages this&lt;/strong&gt;. In 99% of the cases, you shouldn't care about this, but things can get tricky when working with child processes in your own project. Can you feel the inception happening here? &lt;strong&gt;#child-process-inception&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you want to know more about &lt;a href="https://lisk.io"&gt;Lisk&lt;/a&gt; first, check out this short &lt;a href="https://www.youtube.com/watch?v=BnMrIgSoiJQ"&gt;explainer clip&lt;/a&gt; and our &lt;a href="https://lisk.io/documentation"&gt;documentation&lt;/a&gt;!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To give you a better understanding of how this is relevant to our &lt;strong&gt;"npm vs node" problem&lt;/strong&gt;, let's talk about how we are running Lisk Core. For those who don't know what Lisk Core is, essentially, it is a program that implements the Lisk Protocol which &lt;strong&gt;includes consensus, block creation, transaction handling, peer communication, etc. Every machine must set it up to run a node that allows for participation in the network.&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Intro to PM2, a production process manager for Node.js apps.
&lt;/h1&gt;

&lt;p&gt;In our case, we use &lt;a href="https://pm2.keymetrics.io/"&gt;PM2&lt;/a&gt; to restart the application upon failure. PM2 is a production process manager for Node.js applications with a built-in load balancer. It allows you to keep applications alive forever, to reload them without downtime and to facilitate common system admin tasks.&lt;/p&gt;

&lt;p&gt;A few weeks ago, we decided to provide the ability to run the &lt;code&gt;http_api&lt;/code&gt; module as a child process to improve the overall efficiency of the Lisk Core application while using the same allocated resources.&lt;/p&gt;

&lt;h1&gt;
  
  
  Rationale behind the decision to run http_api module as a child process.
&lt;/h1&gt;

&lt;p&gt;The idea behind this decision was mainly funded by the fact that functionally isolated components can form the basis of a multi-process application, in order to utilize the potential of multiple hardware cores of the physical processor if available. Also, to design each component in a resilient way to tackle brittleness of the multi-processing. This means that a failure of one component will have minimal impact on other components and that components can recover individually. More information about child processes can be found in our &lt;a href="https://github.com/LiskHQ/lips/blob/master/proposals/lip-0005.md"&gt;proposal&lt;/a&gt; to introduce a new flexible, resilient and modular architecture for &lt;a href="https://lisk.io/"&gt;Lisk Core&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  We were not able to gracefully exit Lisk Core with npm.
&lt;/h1&gt;

&lt;p&gt;While implementing child processes for the &lt;code&gt;http_api&lt;/code&gt; module, Lightcurve Backend Developer Lucas Silvestre discovered that Lisk Core was not exiting gracefully while &lt;a href="https://github.com/LiskHQ/lisk-sdk/issues/3201#issuecomment-477551495"&gt;running the &lt;code&gt;http_api&lt;/code&gt; module as a child process&lt;/a&gt; using PM2. This resulted in a tricky situation where the &lt;code&gt;http_api&lt;/code&gt; kept on running in the background whenever the main process (Lisk Core) crashed.&lt;/p&gt;

&lt;p&gt;Whenever this happens, PM2 will attempt to recover the Lisk Core process. However, this would spawn a new &lt;code&gt;http_api&lt;/code&gt; process which was not possible as the port was already in use because of the cleanup process not being called. The resulted in PM2 not being able to restore the application which is a big issue when running a blockchain node that is part of the network. In this case, the user has to manually restart the blockchain node which we absolutely want to avoid.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wBL_Xnn_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/uafp72w1cuu8vzq1oyws.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wBL_Xnn_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/uafp72w1cuu8vzq1oyws.png" alt="Managing Lisk Core with Node command"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Running Lisk Core with node command
&lt;/h1&gt;

&lt;p&gt;This issue made us aware of the difference between npm and node and made us reconsider the way we were running Lisk Core. Previously, we just accepted the &lt;code&gt;npm start&lt;/code&gt; industry standard as the go-to way of running an application.&lt;/p&gt;

&lt;p&gt;Later, we found the best practices provided by the docker-node &lt;a href="https://github.com/nodejs/docker-node/blob/master/docs/BestPractices.md"&gt;GitHub repository&lt;/a&gt; dedicated to Dockerizing Node.js applications. Here, a clear warning message can be found about the usage of npm inside of a Dockerfile or any other higher-level application management tool like PM2.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"When creating an image, you can bypass the package.json's start command and bake it directly into the image itself. First off this reduces the number of processes running inside of your container. Secondly, it causes exit signals such as SIGTERM and SIGINT to be received by the Node.js process instead of npm swallowing them."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Whenever we tried to exit Lisk Core or the application crashed, a SIGINT signal is sent to the application. In Node.js, you can listen for this signal and execute a cleanup function in order to gracefully exit the application. In our case, we are removing various listeners and pass the SIGINT signal to the child process in order to exit this one gracefully as well.&lt;/p&gt;

&lt;p&gt;As stated by &lt;em&gt;docker-node&lt;/em&gt;, npm swallows this signal and does not trigger our listeners for the SIGINT signal causing the application to not being able to clean up gracefully. That's also the reason why the &lt;code&gt;http_api&lt;/code&gt; module kept running inside of PM2.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/nickparsons"&gt;Nick Parson&lt;/a&gt;, an expert when it comes to running Node applications with PM2 also mentions the fact that it is important to &lt;strong&gt;gracefully shut down your application in order to maximize robustness and enable fast startup&lt;/strong&gt; (no downtime) when using PM2.&lt;/p&gt;

&lt;h1&gt;
  
  
  Termination signals: what are SIGKILL, SIGTERM, and SIGINT?
&lt;/h1&gt;

&lt;p&gt;We have to dive quite deep to find out what these signals are about. These signals are part of a collection of signals to tell a process to terminate, actually many more exist, and can be found in the documentation provided by &lt;em&gt;gnu.org&lt;/em&gt; under &lt;a href="https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html/"&gt;section 24.2.2 Termination Signals&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SIGKILL: "The SIGKILL signal is used to cause immediate program termination. It cannot be handled or ignored, and is therefore always fatal. It is also not possible to block this signal."&lt;/li&gt;
&lt;li&gt;SIGTERM: "The SIGTERM signal is a generic signal used to cause program termination. Unlike SIGKILL, this signal can be blocked, handled, and ignored. It is the normal way to politely ask a program to terminate." Interesting to know that the shell command kill generates SIGTERM by default.&lt;/li&gt;
&lt;li&gt;SIGINT: "The SIGINT ('&lt;em&gt;&lt;strong&gt;program interrupt&lt;/strong&gt;&lt;/em&gt;') signal is sent when the user types the INTR character (normally &lt;code&gt;C-c&lt;/code&gt;)." Developers will probably be more familiar with the &lt;code&gt;CTRL/CMD+C&lt;/code&gt; command to interrupt a running process in the shell.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Moving Docker and PM2 to Node.
&lt;/h1&gt;

&lt;p&gt;This made us decide to get rid of &lt;code&gt;npm start&lt;/code&gt; and replacing it by the node command. The &lt;code&gt;start&lt;/code&gt; command was being used in both the Dockerfile as the PM2 run file.&lt;/p&gt;

&lt;p&gt;The following image shows a snippet of the typical &lt;code&gt;ENTRYPOINT&lt;/code&gt; for Docker. Previously, this would contain &lt;code&gt;ENTRYPOINT ["npm", "start"]&lt;/code&gt;. This file can be found now in our new &lt;a href="https://github.com/LiskHQ/lisk-core/blob/master/docker/docker-compose.yml#L19"&gt;Lisk Core repositor&lt;/a&gt; which is extracted from the Lisk-SDK Monorepo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gzUw0qJo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/i0lwf9h0dw47ru02dxzj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gzUw0qJo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/i0lwf9h0dw47ru02dxzj.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lisk-SDK Dockerfile.Also, the same applies to the &lt;code&gt;pm2-lisk.json&lt;/code&gt; file which contains the PM2 configuration for starting Lisk Core. The &lt;code&gt;script&lt;/code&gt; property now contains the relative path to the &lt;code&gt;index&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mZXFC3hj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/v2t9cek3d5h5wtszj9yf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mZXFC3hj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/v2t9cek3d5h5wtszj9yf.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Learn how to reproduce the issue in 3 steps.
&lt;/h1&gt;

&lt;p&gt;We can find a cool &lt;a href="https://github.com/npm/npm/issues/4603#issue-26860428"&gt;snippet created by GitHub user EvanTahler&lt;/a&gt; addressing the above-mentioned issue. Let's reproduce this!&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1. Create package.json and app.js
&lt;/h2&gt;

&lt;p&gt;To emulate this issue, you need to create two files (&lt;code&gt;package.json&lt;/code&gt; and &lt;code&gt;app.js&lt;/code&gt;) in the same directory. Make sure you have Node.js version &lt;code&gt;10.x&lt;/code&gt; or higher installed on your machine to run the snippet with the node command. As we don't need any code dependencies, we don't have to install anything else.&lt;/p&gt;

&lt;h3&gt;
  
  
  Package.json
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&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;test&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;scripts&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;start&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;node ./app.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  App.js
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SIGINT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="kd"&gt;function&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SIGINT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="nx"&gt;shutDown&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SIGTERM&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SIGTERM&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="nx"&gt;shutDown&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&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="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;shutDown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;off-ing...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x&lt;/span&gt;&lt;span class="dl"&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="kd"&gt;function&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bye!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&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;string&lt;/span&gt;&lt;span class="p"&gt;);&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Snippet clarification&lt;/strong&gt; - The snippet will print a dot every 0.5 seconds and listens for the SIGINT and SIGTERM signals. Once one of the two termination signals is received, we will delay the shutdown by 5 seconds (5 * 1000ms) and print out "bye!".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before running this snippet&lt;/strong&gt;, I want to show you how a killed process is indicated in your terminal when hitting &lt;code&gt;CTRL/CMD+C&lt;/code&gt;. You can notice it by the &lt;code&gt;^C&lt;/code&gt; characters.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--S_SqBbAk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/c5rj8qxnc81nvg35hbwh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--S_SqBbAk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/c5rj8qxnc81nvg35hbwh.png" alt="Killed with SIGINT"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Shows Lisk Core running for exactly 17 minutes after getting killed with the SIGINT signal.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2. Run the snippet with node.
&lt;/h2&gt;

&lt;p&gt;Now we know how the SIGINT is represented in our terminal, let's start the snippet with &lt;code&gt;node app.js&lt;/code&gt;. Let it run for 5 seconds, and hit &lt;code&gt;CTRL/CMD+C&lt;/code&gt;. You will see that the kill signal is properly handled by Node and waits for 5 more seconds before shutting down.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--97uwVgsJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/btquuiraboam0jyyjvfg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--97uwVgsJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/btquuiraboam0jyyjvfg.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3. Run the snippet with npm start
&lt;/h2&gt;

&lt;p&gt;However, when we run the snippet with &lt;code&gt;npm start&lt;/code&gt;, you will notice two kill signals being received. As we now know, the start command will run &lt;code&gt;node app.js&lt;/code&gt; as a child process. So, when receiving &lt;code&gt;^C&lt;/code&gt;, it will try to exit the npm process and pass this termination signal to the child which causes the problem that the main process exits but the child is still active for 5 more seconds.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TcpSOS9---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/165z815rgx2tjyws9zaq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TcpSOS9---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/165z815rgx2tjyws9zaq.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;As explained before, this will give all sorts of problems when you try to listen for termination signals while running applications with npm start, especially when operating child processes.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Interested in learning how to set up and run your &lt;strong&gt;own Lisk node&lt;/strong&gt;? More information can be found in the &lt;strong&gt;&lt;a href="https://lisk.io/documentation/lisk-core/setup"&gt;Lisk Core documentation&lt;/a&gt;&lt;/strong&gt; on the website. You can choose between the binary setup which is the default (and most simple) installation technique. Other options include running Lisk Core with Docker to support other platforms or for more advanced users, it is possible to build from Lisk Core.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Because of this &lt;strong&gt;"child process inception"&lt;/strong&gt;, the &lt;code&gt;http_api&lt;/code&gt; module could not gracefully exit and kept on running. The only way to stop this process is by using a shell command that kills all Node processes: &lt;code&gt;sudo killall node&lt;/code&gt; (or target the specific process ID to be killed). Luckily, this could be easily resolved by using node to start the application.&lt;/p&gt;

&lt;h1&gt;
  
  
  Best Practices for Handling Node.js Applications
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://twitter.com/felixge"&gt;Felix Geisendörfer&lt;/a&gt;, an early contributor of Node.js, makes it very clear how to handle crashed applications:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Oe9CwLm1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/01ono5lj88n15yv5j5o1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Oe9CwLm1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/01ono5lj88n15yv5j5o1.png" alt=""&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Source: &lt;a href="https://fr.slideshare.net/the_undefined/nodejs-best-practices-10428790/29-Deployment"&gt;Node.js Best Practices SlideShare&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What does the above teach us?&lt;/strong&gt; Avoid spinning up your application through &lt;code&gt;npm start&lt;/code&gt; but use node instead. Also, if something goes wrong, exit the process gracefully and accept it. Felix recommends using higher level tools like PM2 to deal with recovering and restarting the application.&lt;/p&gt;

&lt;p&gt;We learned from this that you not always should take standards for granted. It is sometimes better to keep things simple and run it with a simple node command.&lt;/p&gt;

&lt;p&gt;To conclude what we did at Lisk, we decided to solve the issue by changing the &lt;code&gt;npm start&lt;/code&gt; command to &lt;code&gt;node src/index&lt;/code&gt; in both the PM2 run configuration and Dockerfile. Now, upon receiving a SIGINT signal, the node process receives this directly and can communicate the SIGINT signal to its child processes so every process can be exited gracefully.&lt;/p&gt;

&lt;p&gt;Therefore, PM2 can easily restart the application without any downtime. Running our application via this setup allows us to deploy a more stable application which is utterly important for creating a stable blockchain network.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lisk empowers individuals to create a more decentralized, efficient and transparent global economy. We welcome you to join us in our mission:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://mailchi.mp/lisk/newsletter"&gt;Newsletter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://research.lisk.io/"&gt;Lisk Research&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lisk.chat/"&gt;Lisk.chat&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/Lisk/"&gt;Reddit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>npm</category>
      <category>blockchain</category>
    </item>
  </channel>
</rss>
