<?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: Son Goku</title>
    <description>The latest articles on DEV Community by Son Goku (@hunterjsbit).</description>
    <link>https://dev.to/hunterjsbit</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%2F435853%2F4c9044ca-873b-4b05-ae0b-0e44927c43ad.png</url>
      <title>DEV Community: Son Goku</title>
      <link>https://dev.to/hunterjsbit</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hunterjsbit"/>
    <language>en</language>
    <item>
      <title>How to Create a Gif to Video converter 😎 Vue + Wasm</title>
      <dc:creator>Son Goku</dc:creator>
      <pubDate>Tue, 05 Jan 2021 19:06:28 +0000</pubDate>
      <link>https://dev.to/hunterjsbit/how-to-create-a-gif-to-video-converter-vue-wasm-1dd4</link>
      <guid>https://dev.to/hunterjsbit/how-to-create-a-gif-to-video-converter-vue-wasm-1dd4</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XoG26zZr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/66i3l6xzutu0ubk2w7ui.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XoG26zZr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/66i3l6xzutu0ubk2w7ui.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can view here what we are building&lt;br&gt;
&lt;a href="https://hunterjs-bit.github.io/vue_wasm_gif_to_video/"&gt;https://hunterjs-bit.github.io/vue_wasm_gif_to_video/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find the full source code for this tutorial in my repo:&lt;br&gt;
&lt;a href="https://github.com/HunterJS-bit/vue_wasm_gif_to_video"&gt;https://github.com/HunterJS-bit/vue_wasm_gif_to_video&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;What you will build ?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You are going to build an simple application that provides GIF to Video conversion. User can preview converted video and download it. Normally for this user would have to write some server code for handling conversion but we can do it all on client side thanx to WASM :)&lt;/p&gt;
&lt;h4&gt;
  
  
  Prerequisites
&lt;/h4&gt;

&lt;p&gt;You should know basic programming. This is fairly easy project that you can do for fun. We are using &lt;strong&gt;Vue&lt;/strong&gt; &amp;amp; &lt;strong&gt;Wasm&lt;/strong&gt; but you can use any other framework for this.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Lets get started&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PpgXKvrC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sc0yi2b4z83iyuclj697.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PpgXKvrC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sc0yi2b4z83iyuclj697.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First things first, lets generate Vue project and install needed dependencies than we will talk a bit more about the code.&lt;/p&gt;
&lt;h3&gt;
  
  
  Initial Setup With Vue CLI
&lt;/h3&gt;

&lt;p&gt;For your reference, please see the &lt;a href="https://cli.vuejs.org/guide/installation.html"&gt;Vue CLI documentation&lt;/a&gt;. Follow these steps to install and initialize via Vue CLI:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Install Vue CLI 3&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;```
 npm install -g @vue/cli
```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: Initialize your project with Vue CLI 3&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;```
   vue create vue-app
```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4: Serve up a localhost&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once everything is installed, navigate to the project folder and run &lt;code&gt;npm run serve&lt;/code&gt; in the terminal to serve up a localhost.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Open your browser, and you will get screen simmilar to this one.&lt;/em&gt;&lt;/p&gt;

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

&lt;h3&gt;
  
  
  &lt;strong&gt;Install dependencies&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We will use &lt;a href="https://www.npmjs.com/package/@ffmpeg/ffmpeg"&gt;&lt;strong&gt;ffmpeg.wasm&lt;/strong&gt;&lt;/a&gt; library to allow us to convert gif to video. Ffmep library is a port of popular &lt;a href="https://ffmpeg.org/"&gt;FFmpeg library&lt;/a&gt; and provides simple to use APIs for audio, video manipulation.&lt;/p&gt;

&lt;p&gt;Run command follwing command, to install ffmpeg:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @ffmpeg/ffmpeg @ffmpeg/core
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;File Structure Overview&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The component tree itself is nothing groundbreaking, We will use only one component:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;VideoMaker.vue&lt;/em&gt; - Renders the Vue video converter component&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So create your new component VideoMaker.vue.&lt;/p&gt;

&lt;p&gt;The basic structure of a Vue single file component includes your markup, script, and style tags.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;

  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
export default {
 name: 'VideoMaker',
}
&amp;lt;/script&amp;gt;

&amp;lt;style scoped&amp;gt;

&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we will add form, and component logic&lt;/p&gt;

&lt;h3&gt;
  
  
  Add Form, Load Fmmpeg Library and Style component
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div class="gif-converter"&amp;gt;
    &amp;lt;div class="upload-form"&amp;gt;
      &amp;lt;h2&amp;gt;Upload your Gif&amp;lt;/h2&amp;gt;
      &amp;lt;form &amp;gt;
        &amp;lt;div class="upload-box" :style="{ backgroundImage: 'url(' + gifImage + ')' }"&amp;gt;
          &amp;lt;div class="upload-icon" v-if="!gifImage"&amp;gt;

          &amp;lt;/div&amp;gt;
          &amp;lt;input type="file" id="fileInput" name="filename" /&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/form&amp;gt;
      &amp;lt;div class="action-bar mt-10"&amp;gt;
        &amp;lt;button class="convert-btn"&amp;gt;Convert to Video&amp;lt;/button&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div class="preview-form"&amp;gt;
      &amp;lt;h2&amp;gt;Result&amp;lt;/h2&amp;gt;
      &amp;lt;div class="video-wrapper"&amp;gt;
        &amp;lt;div class="loader" v-if="loading"&amp;gt;
          &amp;lt;h2 class="loading-text"&amp;gt;Loading ...&amp;lt;/h2&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;video v-if="video" id="output-video" controls :src="video"&amp;gt;&amp;lt;/video&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import { createFFmpeg, fetchFile } from "@ffmpeg/ffmpeg";
// create ffmpeg instance
const ffmpeg = createFFmpeg({ log: true });

export default {
  name: "VideoMaker",
  async created() {
    // load ffmpeg when component is created
    await ffmpeg.load();
  },
  data() {
    return {
      gifImage: null, // gif image is loadaded
      video: null, // video converted
      loading: false // should show loading animation
    };
  },
};
&amp;lt;/script&amp;gt;

&amp;lt;style scoped&amp;gt;
.gif-converter {
  display: flex;
  justify-content: space-around;
  align-items: stretch;
  flex-wrap: wrap;
  padding: 20px 50px;
  background: white;
  box-shadow: 0 15px 20px -15px rgba(0, 0, 0, 0.3),
    0 55px 50px -35px rgba(0, 0, 0, 0.3), 0 85px 60px -25px rgba(0, 0, 0, 0.1);
}
.preview-form video {
  max-width: 100%;
  width: 100%;
  height: auto;
}
.loader {
  margin-top: 50px;
}
.loader .loading-text {
  font-weight: 100;
  color: #dedede;
}
#fileInput {
  position: absolute;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
}
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I realize that’s a lot to drop on you, but I hope it’s clear enough that most developers would be able to follow it. Clearly there’s a lot of cruft in here. But will try to explain a bit.&lt;/p&gt;

&lt;p&gt;First we Import fetchFile &amp;amp; createFFmpeg methods from &lt;code&gt;ffmpeg/ffmpeg&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const ffmpeg = createFFmpeg({ log: true });&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
 here we create ffmpeg instance for later use&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;await ffmpeg.load();&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
 here we have to wait to load ffmpeg in browser&lt;/p&gt;

&lt;p&gt;As you can see towards in our template, we have 2 forms. First form is for uploading gif and second form is for rendering converted video in form.&lt;/p&gt;

&lt;p&gt;And we have data properties &lt;code&gt;gifImage&lt;/code&gt;, &lt;code&gt;video&lt;/code&gt;, &lt;code&gt;loading&lt;/code&gt; that are manily used for toggling visibility of component&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;And now add logic&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; methods: {
    uploadFile(e) {
      const file = e.target.files[0];
      this.gifImage = URL.createObjectURL(file);
    },
    /**
     * Handles gif to video conversion
     */
    async convertToVideo() {
      this.video = null;
      ffmpeg.FS("writeFile", "randGif.gif", await fetchFile(this.gifImage)); // load gif image into ffmpeg
      this.loading = true;
      await ffmpeg.run("-f", "gif", "-i", "randGif.gif", "output.mp4");  // convert gif to mp4
      const data = ffmpeg.FS("readFile", "output.mp4");
      this.video = URL.createObjectURL(
        new Blob([data.buffer], { type: "video/mp4" })
      ); // create URL representing video field
      this.loading = false;
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see towards here we have two methods &lt;/p&gt;

&lt;p&gt;&lt;code&gt;uploadFile&lt;/code&gt; - method is used to get Gif image that user uploads&lt;br&gt;
&lt;code&gt;convertToVideo&lt;/code&gt; - method handles video conversion, here as you can see, first we load gif image into ffmpeg library, then we use &lt;code&gt;ffmpeg.run&lt;/code&gt; command to do conversion, and at last we get URL of created video file&lt;/p&gt;

&lt;h4&gt;
  
  
  and here is updated template
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div class="gif-converter"&amp;gt;
    &amp;lt;div class="upload-form"&amp;gt;
      &amp;lt;h2&amp;gt;Upload your Gif&amp;lt;/h2&amp;gt;
      &amp;lt;form @submit.prevent="uploadFile"&amp;gt;
        &amp;lt;div class="upload-box" :style="{ backgroundImage: 'url(' + gifImage + ')' }"&amp;gt;
          &amp;lt;div class="upload-icon" v-if="!gifImage"&amp;gt;
            &amp;lt;upload-icon&amp;gt;&amp;lt;/upload-icon&amp;gt;
          &amp;lt;/div&amp;gt;
          &amp;lt;input type="file" id="fileInput" @change="uploadFile" name="filename" /&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/form&amp;gt;
      &amp;lt;div class="action-bar mt-10"&amp;gt;
        &amp;lt;button class="convert-btn" :disabled="!gifImage" @click="convertToVideo"&amp;gt;Convert to Video&amp;lt;/button&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div class="preview-form"&amp;gt;
      &amp;lt;h2&amp;gt;Result&amp;lt;/h2&amp;gt;
      &amp;lt;div class="video-wrapper"&amp;gt;
        &amp;lt;div class="loader" v-if="loading"&amp;gt;
          &amp;lt;h2 class="loading-text"&amp;gt;Loading ...&amp;lt;/h2&amp;gt;
          &amp;lt;loader-icon&amp;gt;&amp;lt;/loader-icon&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;video v-if="video" id="output-video" controls :src="video"&amp;gt;&amp;lt;/video&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In template we just attached on click &lt;code&gt;convertToVideo&lt;/code&gt; and &lt;code&gt;uploadFile&lt;/code&gt; methods.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Closing thoughts&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Now that you've built this project, you should have a firm understanding of how Vue.js is used with Wasm. For additional practice, try implementing more features and building on the existing structure. &lt;/p&gt;

&lt;p&gt;With your newfound knowledge, you can add features such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;add backward conversion (from video to gif)&lt;/li&gt;
&lt;li&gt;add different formats when converting video&lt;/li&gt;
&lt;li&gt;add animations&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Full source code is available &lt;a href="https://github.com/HunterJS-bit/vue_wasm_gif_to_video"&gt;here&lt;/a&gt;. You are welcome to join in and feel free to contribute&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>javascript</category>
      <category>vue</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Building Context Menu in Vue.js</title>
      <dc:creator>Son Goku</dc:creator>
      <pubDate>Mon, 12 Oct 2020 23:09:47 +0000</pubDate>
      <link>https://dev.to/hunterjsbit/building-context-menu-in-vue-js-2cbn</link>
      <guid>https://dev.to/hunterjsbit/building-context-menu-in-vue-js-2cbn</guid>
      <description>&lt;p&gt;Today we are going to create our context menu with VueJS from scratch, with traditional "Hello World" example. &lt;/p&gt;

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

&lt;h1&gt;
  
  
  &lt;strong&gt;Create fresh Vue Project&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Let's start by creating new project and running the application.&lt;/p&gt;

&lt;p&gt;The first you have to do is to install the &lt;a href="https://cli.vuejs.org/guide/installation.html" rel="noopener noreferrer"&gt;Vue CLI&lt;/a&gt; on your computer&lt;/p&gt;

&lt;p&gt;To create a new project, run:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;
 create &lt;span class="nt"&gt;&amp;lt;enter&lt;/span&gt; &lt;span class="na"&gt;the&lt;/span&gt; &lt;span class="na"&gt;app&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;

&lt;p&gt;More about Vue cli, you can see &lt;a href="https://cli.vuejs.org/guide/creating-a-project.html#vue-create" rel="noopener noreferrer"&gt;here&lt;/a&gt; from their official docs.&lt;/p&gt;

&lt;p&gt;It will generate new Project with following initial file structure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;index.html&lt;/li&gt;
&lt;li&gt;src/App.vue&lt;/li&gt;
&lt;li&gt;src/main.js&lt;/li&gt;
&lt;li&gt;src/assets/logo.png&lt;/li&gt;
&lt;li&gt;src/components/HelloWorld.vue&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Start Project&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Now lets run our generated project by Vue CLI&lt;/p&gt;

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

cd &amp;lt;project-name&amp;gt;
npm install
npm run serve


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

&lt;/div&gt;
&lt;h1&gt;
  
  
  &lt;strong&gt;The Vue Instance&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;We will open now &lt;em&gt;App.vue&lt;/em&gt; there will be following code:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;lt;div id="app"&amp;gt;
  &amp;lt;img width="25%" src="./assets/logo.png"&amp;gt;
  &amp;lt;HelloWorld/&amp;gt;
&amp;lt;/div&amp;gt;


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

&lt;/div&gt;

&lt;p&gt;For now we can remove HelloWorld component and create new component named &lt;code&gt;ContextMenu.vue&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Open you ContextMenu.vue and add basic template&lt;/p&gt;

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

&amp;lt;div class="context-menu" ref="context" tabindex="0"&amp;gt;
        &amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt;
    &amp;lt;/div&amp;gt;


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

&lt;/div&gt;

&lt;p&gt;A bit about code&lt;br&gt;
&lt;em&gt;Slot&lt;/em&gt; will allow us to render components inside of our context menu, and &lt;em&gt;tabIndex&lt;/em&gt; prop will focus element &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Add Styles&lt;/strong&gt;&lt;/p&gt;

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

&amp;lt;style&amp;gt;
.context-menu {
    position: fixed;
    background: white;
    z-index: 999;
    outline: none;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
    cursor: pointer;
}
&amp;lt;/style&amp;gt;


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

&lt;/div&gt;

&lt;p&gt;Now add some logic and full component Code&lt;/p&gt;

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

&amp;lt;template&amp;gt;
&amp;lt;div class="context-menu" v-show="show" :style="style" ref="context" tabindex="0" @blur="close"&amp;gt;
        &amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script&amp;gt;
import Vue from 'vue';

export default {
    name: 'CmpContextMenu',
    props: {
        display: Boolean, // prop detect if we should show context menu
    },
    data() {
        return {
            left: 0, // left position
            top: 0, // top position
            show: false, // affect display of context menu
        };
    },
    computed: {
        // get position of context menu
        style() {
            return {
                top: this.top + 'px',
                left: this.left + 'px',
            };
        },
    },
    methods: { 
        // closes context menu 
        close() {
            this.show = false;
            this.left = 0;
            this.top = 0;
        },
        open(evt) {
            // updates position of context menu 
            this.left = evt.pageX || evt.clientX;
            this.top = evt.pageY || evt.clientY;
            // make element focused 
            // @ts-ignore
            Vue.nextTick(() =&amp;gt; this.$el.focus());
            this.show = true;
        },
    },
};
&amp;lt;/script&amp;gt;
&amp;lt;style&amp;gt;
.context-menu {
    position: fixed;
    background: white;
    z-index: 999;
    outline: none;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
    cursor: pointer;
}
&amp;lt;/style&amp;gt;


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

&lt;/div&gt;

&lt;p&gt;The code is self self explanatory explained &lt;code&gt;open&lt;/code&gt; method opens context menu, &lt;code&gt;close&lt;/code&gt; method closes the context menu, and computed propert &lt;code&gt;styles&lt;/code&gt; that will return position of context menu.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Usage&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Now import your new component into &lt;strong&gt;App.vue&lt;/strong&gt;, and start show your own context menu.&lt;/p&gt;

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

&amp;lt;div id="app"&amp;gt;
  &amp;lt;img width="25%" src="./assets/logo.png"&amp;gt;
 &amp;lt;context-menu :display="showContextMenu" ref="menu"&amp;gt;
      &amp;lt;ul&amp;gt;
         &amp;lt;li&amp;gt; List item 1 &amp;lt;/li&amp;gt;
         &amp;lt;li&amp;gt; List item 2 &amp;lt;/li&amp;gt;
      &amp;lt;/ul&amp;gt;
&amp;lt;/context-menu&amp;gt;

&amp;lt;button @click='openContextMenu'&amp;gt;activate context menu&amp;lt;/button&amp;gt;
&amp;lt;/div&amp;gt;

&amp;lt;script&amp;gt;
import ContextMenu from './ContextMenu';


export default {
  components: {
    ContextMenu,
  },
  data() {
     return { showContextMenu: false }
  },
  methods: {
    openContextMenu(e) {
         this.$refs.menu.open(e);
    }
  }
}
&amp;lt;/script&amp;gt;


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

&lt;/div&gt;

&lt;p&gt;With a little edit you could create something looking like this:&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;Note&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is just a basic and really simple example how you could create context menu  with as little code as possible.&lt;/p&gt;

&lt;p&gt;As is almost always the case, you'll need to pick the approach that makes the most sense for your use-case.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>vue</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Did you relocate ? Tell me your rellocation experiences</title>
      <dc:creator>Son Goku</dc:creator>
      <pubDate>Tue, 15 Sep 2020 23:55:57 +0000</pubDate>
      <link>https://dev.to/hunterjsbit/did-you-relocate-tell-me-your-rellocation-experiences-4ibg</link>
      <guid>https://dev.to/hunterjsbit/did-you-relocate-tell-me-your-rellocation-experiences-4ibg</guid>
      <description>&lt;p&gt;I'm getting offers for relocation outside my country,  I'm wondering if it's common for developers to relocate to country ? If yes what are your experiences ? I'm willing to move just about anywhere for a dev position, but I don't know how commonly this happens.How should I go about this? Should I watch out for some red flags and what are they ?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>discuss</category>
      <category>career</category>
    </item>
    <item>
      <title>Build Multiselect component in few lines</title>
      <dc:creator>Son Goku</dc:creator>
      <pubDate>Sat, 05 Sep 2020 01:44:52 +0000</pubDate>
      <link>https://dev.to/hunterjsbit/build-multiselect-component-in-react-in-few-lines-4m1c</link>
      <guid>https://dev.to/hunterjsbit/build-multiselect-component-in-react-in-few-lines-4m1c</guid>
      <description>&lt;h1&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h1&gt;

&lt;h2&gt;
  
  
  What We Will Be Building
&lt;/h2&gt;

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

&lt;p&gt;In this example, i will show you how you can build sime  React Multiselect component. You can see basic logic behind component, and how you can use to build something simmilar yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is multiselect
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;React Multiselect&lt;/strong&gt; - is a component that allows users to tick multiple options. Its implementation is quite simple, and in exchange brings a lot of UX value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;This tutorial assumes that you have working knowledge of React&lt;/li&gt;
&lt;li&gt;We are going to Use React Hooks&lt;/li&gt;
&lt;li&gt;For css library I used here &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;TailwindCSS&lt;/a&gt;, but you can use other if you like&lt;/li&gt;
&lt;li&gt;Before we get started, ensure that you have Node, Yarn, or npm installed in your environment.&lt;/li&gt;
&lt;li&gt;Have a Web browser ofcourse&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Creating the React App&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Now that we have all the information we will need to connect our application and we know what are we building, let's start building out our application!&lt;/p&gt;

&lt;p&gt;Open your &lt;strong&gt;teminal&lt;/strong&gt;, once there, we are going to be using the &lt;code&gt;create-react-app&lt;/code&gt; command to get our application running. Run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-react-app multiselect
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now to explain a bit.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;npx&lt;/code&gt; command will install and run the command &lt;code&gt;create-react-app&lt;/code&gt; for us. The last part of that command is the name of our app. We are going to be naming our app &lt;code&gt;multiselect&lt;/code&gt;, feel free to name it whatever you want.&lt;/p&gt;

&lt;p&gt;Once &lt;strong&gt;cli&lt;/strong&gt; has finished creating the project folder you can cd into it, and run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd multiselect
npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open your brower in type into url -&amp;gt; &lt;code&gt;localhost:3000&lt;/code&gt; to see our default React start page.&lt;/p&gt;

&lt;p&gt;It will look like this:&lt;/p&gt;

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

&lt;h1&gt;
  
  
  &lt;strong&gt;Install TailwindCSS&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Next step is to install and configure tailwindcss. So I do not want to make this article too long, so you can check out these 2 guides on how to setup React with Tailwind:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/0x96f/react-and-tailwind-css-setup-51h0"&gt;React &amp;amp; Tailwind Setup&lt;/a&gt;&lt;br&gt;
&lt;a href="https://blog.logrocket.com/create-react-app-and-tailwindcss/" rel="noopener noreferrer"&gt;Configure React with Tailwind&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Anyway If you do not want to use Tailwindcss, you can choose any other css framework (Bootstrap, Foundation etc), the code will work just fine.&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;strong&gt;Our Components&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;We will need 2 files, for this one to hold &lt;strong&gt;Multiselect&lt;/strong&gt; component &amp;amp; one to hold &lt;strong&gt;Dropdown&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Within the &lt;code&gt;/src&lt;/code&gt; folder, create a folder named &lt;code&gt;/components&lt;/code&gt;. With that folder, create three files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;./Multiselect.js&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;./Dropdown.js&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Multiselect Component&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now we will start working on MultiSelect component.&lt;br&gt;
Open you Multiselect.js &amp;amp; paste following code inside it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useState } from "react";

const MultiSelect = () =&amp;gt; {
  const [items, setItems] = useState(["john", "milos", "steph", "kathreine"]);
  const [selectedItems, setSelected] = useState([]);

  return (
    &amp;lt;div className="autcomplete-wrapper"&amp;gt;
      &amp;lt;div className="autcomplete"&amp;gt;
        &amp;lt;div className="w-full flex flex-col items-center mx-auto"&amp;gt;
          &amp;lt;div className="w-full"&amp;gt;
            &amp;lt;div className="flex flex-col items-center relative"&amp;gt;
              &amp;lt;div className="w-full "&amp;gt;
                &amp;lt;div className="my-2 p-1 flex border border-gray-200 bg-white rounded "&amp;gt;
                  &amp;lt;div className="flex flex-auto flex-wrap"&amp;gt;
                    {selectedItems.map((tag, index) =&amp;gt; {
                      return (
                        &amp;lt;div
                          key={index}
                          className="flex justify-center items-center m-1 font-medium py-1 px-2 bg-white rounded-full text-teal-700 bg-teal-100 border border-teal-300 "
                        &amp;gt;
                          &amp;lt;div className="text-xs font-normal leading-none max-w-full flex-initial"&amp;gt;
                            {tag}
                          &amp;lt;/div&amp;gt;
                          &amp;lt;div className="flex flex-auto flex-row-reverse"&amp;gt;
                            &amp;lt;div&amp;gt;

                            &amp;lt;/div&amp;gt;
                          &amp;lt;/div&amp;gt;
                        &amp;lt;/div&amp;gt;
                      );
                    })}
                    &amp;lt;div className="flex-1"&amp;gt;
                      &amp;lt;input
                        placeholder=""
                        className="bg-transparent p-1 px-2 appearance-none outline-none h-full w-full text-gray-800"
                      /&amp;gt;
                    &amp;lt;/div&amp;gt;
                  &amp;lt;/div&amp;gt;
                  &amp;lt;div className="text-gray-300 w-8 py-1 pl-2 pr-1 border-l flex items-center border-gray-200"&amp;gt;
                    &amp;lt;button className="cursor-pointer w-6 h-6 text-gray-600 outline-none focus:outline-none"&amp;gt;

                    &amp;lt;/button&amp;gt;
                  &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
              &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default MultiSelect;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Adding Dropdown&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let's build out our dropdown now. We need our dropdown to open options and allow users to add/remove tags. &lt;/p&gt;

&lt;p&gt;Now will introduce new Component &lt;code&gt;Dropdown.js&lt;/code&gt;, do not forget to create it if you didn't already, and there put view of our dropdown&lt;/p&gt;

&lt;p&gt;Also we will Updated &lt;strong&gt;Multiselect component&lt;/strong&gt; with &lt;em&gt;showing/hidding&lt;/em&gt; dropdown on click.&lt;/p&gt;

&lt;p&gt;Here are our now our two updated components:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dropdown.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from "react";  

const Dropdown = ({ list }) =&amp;gt; {  
  return (  
    &amp;lt;div  
      id="dropdown"  
      className="absolute shadow top-100 bg-white z-40 w-full lef-0 rounded max-h-select overflow-y-auto "  
    &amp;gt;  
      &amp;lt;div className="flex flex-col w-full"&amp;gt;  
        {list.map((item, key) =&amp;gt; {  
          return (  
            &amp;lt;div  
              key={key}  
              className="cursor-pointer w-full border-gray-100 rounded-t border-b hover:bg-teal-100"  
            &amp;gt;  
              &amp;lt;div className="flex w-full items-center p-2 pl-2 border-transparent border-l-2 relative hover:border-teal-100"&amp;gt;  
                &amp;lt;div className="w-full items-center flex"&amp;gt;  
                  &amp;lt;div className="mx-2 leading-6  "&amp;gt;{item}&amp;lt;/div&amp;gt;  
                &amp;lt;/div&amp;gt;  
              &amp;lt;/div&amp;gt;  
            &amp;lt;/div&amp;gt;  
          );  
        })}  
      &amp;lt;/div&amp;gt;  
    &amp;lt;/div&amp;gt;  
  );  
};  

export default Dropdown;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Multiselect.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useState } from 'react';
// import dropdown component
import Dropdown from './Dropdown';


const Multiselect = () =&amp;gt; {
    // state showing if dropdown is open or closed
    const [dropdown, setDropdown] = useState(false);
    // managing dropdown items (list of dropdown items)
    const [items, setItems] = useState(['john', 'milos', 'steph', 'kathreine']);
    // contains multiselect items
    const [selectedItems, setSelected] = useState([]);

    // toggle dropdown open/close  
    const toogleDropdown = () =&amp;gt; {
        setDropdown(!dropdown)
    };

    return (&amp;lt;div className="autcomplete-wrapper"&amp;gt;
        &amp;lt;div className="autcomplete"&amp;gt;
        &amp;lt;div className="w-full flex flex-col items-center mx-auto"&amp;gt;
    &amp;lt;div className="w-full"&amp;gt;
        &amp;lt;div className="flex flex-col items-center relative"&amp;gt;
            &amp;lt;div className="w-full "&amp;gt;
                &amp;lt;div className="my-2 p-1 flex border border-gray-200 bg-white rounded "&amp;gt;
                    &amp;lt;div className="flex flex-auto flex-wrap"&amp;gt;
                        {
                            selectedItems.map((tag, index) =&amp;gt; {
                                return (
                                    &amp;lt;div key={index} className="flex justify-center items-center m-1 font-medium py-1 px-2 bg-white rounded-full text-teal-700 bg-teal-100 border border-teal-300 "&amp;gt;
                                            &amp;lt;div className="text-xs font-normal leading-none max-w-full flex-initial"&amp;gt;{ tag }&amp;lt;/div&amp;gt;
                                            &amp;lt;div className="flex flex-auto flex-row-reverse"&amp;gt;
                                                &amp;lt;div&amp;gt;
                                                    &amp;lt;svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" 
                                                    className="feather feather-x cursor-pointer hover:text-teal-400 rounded-full w-4 h-4 ml-2"&amp;gt;
                                                        &amp;lt;line x1="18" y1="6" x2="6" y2="18"&amp;gt;&amp;lt;/line&amp;gt;
                                                        &amp;lt;line x1="6" y1="6" x2="18" y2="18"&amp;gt;&amp;lt;/line&amp;gt;
                                                    &amp;lt;/svg&amp;gt;
                                                &amp;lt;/div&amp;gt;
                                            &amp;lt;/div&amp;gt;
                                        &amp;lt;/div&amp;gt;)
                            })
                        }
                        &amp;lt;div className="flex-1"&amp;gt;
                            &amp;lt;input placeholder="" className="bg-transparent p-1 px-2 appearance-none outline-none h-full w-full text-gray-800"/&amp;gt;
                        &amp;lt;/div&amp;gt;
                    &amp;lt;/div&amp;gt;
                    &amp;lt;div className="text-gray-300 w-8 py-1 pl-2 pr-1 border-l flex items-center border-gray-200" onClick={toogleDropdown}&amp;gt;
                        &amp;lt;button className="cursor-pointer w-6 h-6 text-gray-600 outline-none focus:outline-none"&amp;gt;
                            &amp;lt;svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="feather feather-chevron-up w-4 h-4"&amp;gt;
                                &amp;lt;polyline points="18 15 12 9 6 15"&amp;gt;&amp;lt;/polyline&amp;gt;
                            &amp;lt;/svg&amp;gt;
                        &amp;lt;/button&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
         { dropdown  ? &amp;lt;Dropdown list={items}&amp;gt;&amp;lt;/Dropdown&amp;gt;: null }
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;

    &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;)
};

export default Multiselect;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Notice what we changed We've added &lt;strong&gt;dropdown component&lt;/strong&gt;, look at the bottom of &lt;strong&gt;Multiselect&lt;/strong&gt; component and added state for dropdown and &lt;code&gt;toogleDropdown&lt;/code&gt; method to to switch between open and close state using: &lt;code&gt;setDropdown(!dropdown)&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Adding Option to Add/Remove Tags
&lt;/h2&gt;

&lt;p&gt;Now this is the last step, we can add 2 methods to add &amp;amp; remove tags to and from multiselect.&lt;/p&gt;

&lt;p&gt;This will give us options to add item to multiselect by clicking on it from dropdown list, and remove it from multiselect by click on X.&lt;/p&gt;

&lt;p&gt;Check Updated Component:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multiselect.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useState } from 'react';
import Dropdown from './Dropdown';


const Multiselect = () =&amp;gt; {
    // state showing if dropdown is open or closed
    const [dropdown, setDropdown] = useState(false);
    // managing dropdown items (list of dropdown items)
    const [items, setItems] = useState(['john', 'milos', 'steph', 'kathreine']);
    // contains selected items
    const [selectedItems, setSelected] = useState([]);


    const toogleDropdown = () =&amp;gt; {
        setDropdown(!dropdown)
    };
    // adds new item to multiselect 
    const addTag = (item) =&amp;gt; {
        setSelected(selectedItems.concat(item));
        setDropdown(false);
    };
    // removes item from multiselect
    const removeTag = (item) =&amp;gt; {
        const filtered = selectedItems.filter((e) =&amp;gt; e !== item);
        setSelected(filtered);
    }

    return (&amp;lt;div className="autcomplete-wrapper"&amp;gt;
        &amp;lt;div className="autcomplete"&amp;gt;
        &amp;lt;div className="w-full flex flex-col items-center mx-auto"&amp;gt;
    &amp;lt;div className="w-full"&amp;gt;
        &amp;lt;div className="flex flex-col items-center relative"&amp;gt;
            &amp;lt;div className="w-full "&amp;gt;
                &amp;lt;div className="my-2 p-1 flex border border-gray-200 bg-white rounded "&amp;gt;
                    &amp;lt;div className="flex flex-auto flex-wrap"&amp;gt;
                        {
                            selectedItems.map((tag, index) =&amp;gt; {
                                return (
                                    &amp;lt;div key={index} className="flex justify-center items-center m-1 font-medium py-1 px-2 bg-white rounded-full text-teal-700 bg-teal-100 border border-teal-300 "&amp;gt;
                                            &amp;lt;div className="text-xs font-normal leading-none max-w-full flex-initial"&amp;gt;{ tag }&amp;lt;/div&amp;gt;
                                            &amp;lt;div className="flex flex-auto flex-row-reverse"&amp;gt;
                                                &amp;lt;div onClick={() =&amp;gt; removeTag(tag)}&amp;gt;
                                                    &amp;lt;svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" 
                                                    className="feather feather-x cursor-pointer hover:text-teal-400 rounded-full w-4 h-4 ml-2"&amp;gt;
                                                        &amp;lt;line x1="18" y1="6" x2="6" y2="18"&amp;gt;&amp;lt;/line&amp;gt;
                                                        &amp;lt;line x1="6" y1="6" x2="18" y2="18"&amp;gt;&amp;lt;/line&amp;gt;
                                                    &amp;lt;/svg&amp;gt;
                                                &amp;lt;/div&amp;gt;
                                            &amp;lt;/div&amp;gt;
                                        &amp;lt;/div&amp;gt;)
                            })
                        }
                        &amp;lt;div className="flex-1"&amp;gt;
                            &amp;lt;input placeholder="" className="bg-transparent p-1 px-2 appearance-none outline-none h-full w-full text-gray-800"/&amp;gt;
                        &amp;lt;/div&amp;gt;
                    &amp;lt;/div&amp;gt;
                    &amp;lt;div className="text-gray-300 w-8 py-1 pl-2 pr-1 border-l flex items-center border-gray-200" onClick={toogleDropdown}&amp;gt;
                        &amp;lt;button className="cursor-pointer w-6 h-6 text-gray-600 outline-none focus:outline-none"&amp;gt;
                            &amp;lt;svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="feather feather-chevron-up w-4 h-4"&amp;gt;
                                &amp;lt;polyline points="18 15 12 9 6 15"&amp;gt;&amp;lt;/polyline&amp;gt;
                            &amp;lt;/svg&amp;gt;
                        &amp;lt;/button&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
         { dropdown  ? &amp;lt;Dropdown list={items} addItem={addTag}&amp;gt;&amp;lt;/Dropdown&amp;gt;: null }
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;

    &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;)
};

export default Multiselect;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Dropdown.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';


const Dropdown = ({list, addItem}) =&amp;gt; {


    return (&amp;lt;div id="dropdown" className="absolute shadow top-100 bg-white z-40 w-full lef-0 rounded max-h-select overflow-y-auto "&amp;gt;
    &amp;lt;div className="flex flex-col w-full"&amp;gt;
        { list.map((item, key) =&amp;gt; {
            return &amp;lt;div key={key} 
            className="cursor-pointer w-full border-gray-100 rounded-t border-b hover:bg-teal-100" 
            onClick={() =&amp;gt; addItem(item)}&amp;gt;
            &amp;lt;div className="flex w-full items-center p-2 pl-2 border-transparent border-l-2 relative hover:border-teal-100" &amp;gt;
                &amp;lt;div className="w-full items-center flex"&amp;gt;
        &amp;lt;   div className="mx-2 leading-6  "&amp;gt;
            { item }
           &amp;lt;/div&amp;gt;
          &amp;lt;/div&amp;gt;
         &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
        })}
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;);

};

export default Dropdown;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;What have we changed, nothing much, we added 2 new methods: &lt;code&gt;addTag&lt;/code&gt;, &lt;code&gt;removeTag&lt;/code&gt; in Multiselect, they will allow use to like their names say remove them and add them to multiselect&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;While this is a very simple tutorial, it shows how far we can get with just few lines of react code (most of the code is css classes from tailwind). &lt;/p&gt;

&lt;p&gt;So what does this all mean? What have you learned? You learned how to create a React  multiselect component with all the basic functionality encapsulated within it. You also learned how to pass values to the component, and how to use useState hook.&lt;/p&gt;

&lt;p&gt;Now don't just stare there go and try buiding something yourself, because that is the fastest way you will learn!&lt;/p&gt;

&lt;p&gt;If you have any questions, please don’t hesitate to leave a &lt;strong&gt;comment&lt;/strong&gt; below.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you liked this post, you can find more on:&lt;/p&gt;

&lt;p&gt;Following me on Twitter:&lt;/p&gt;
&lt;/blockquote&gt;

</description>
    </item>
    <item>
      <title>React  infinite scroll in few lines</title>
      <dc:creator>Son Goku</dc:creator>
      <pubDate>Sun, 09 Aug 2020 22:35:22 +0000</pubDate>
      <link>https://dev.to/hunterjsbit/react-infinite-scroll-in-few-lines-588f</link>
      <guid>https://dev.to/hunterjsbit/react-infinite-scroll-in-few-lines-588f</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is infinite scroll ?
&lt;/h3&gt;

&lt;p&gt;Infinite scrolling is a web-design technique that loads content continuously as the user scrolls down the page, eliminating the need for pagination.&lt;br&gt;
Some sites where you can see usage of infinity scroll are for example: &lt;a href="https://twitter.com/home" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, &lt;a href="https://9gag.com/" rel="noopener noreferrer"&gt;9gag&lt;/a&gt; etc...&lt;/p&gt;
&lt;h2&gt;
  
  
  What are we going to build
&lt;/h2&gt;

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

&lt;p&gt;I know nothing to fancy looking, but you can improve and style it, so it looks better, this is just a basic example and introducting a concept&lt;/p&gt;
&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;This tutorial assumes that you have working knowledge of React&lt;/li&gt;
&lt;li&gt;We are going to Use &lt;a href="https://reactjs.org/docs/hooks-intro.html" rel="noopener noreferrer"&gt;React Hooks&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Before we get started, ensure that you have Node, Yarn, or npm installed in your environment.&lt;/li&gt;
&lt;li&gt;Have a Web browser offcourse&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-react-app infiniteScroll
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Once you have finished creating the project folder you can cd into it, and run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd infiniteScroll 
npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will run the app in development mode and you can view it in the browser using the link &lt;a href="http://localhost:3000/" rel="noopener noreferrer"&gt;http://localhost:3000/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It will look like this:&lt;/strong&gt;&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Component Setup
&lt;/h2&gt;

&lt;p&gt;Create new Infinite scroll component and paste following code inside it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useState  } from 'react';
// styling post container
const divStyle = {
    color: 'blue',
    height: '250px',
    textAlign: 'center',
    padding: '5px 10px',
    background: '#eee',
    marginTop: '15px'
};

// styling container wrapper
const containerStyle = {
    maxWidth: '1280px',
    margin: '0 auto',
}

const InfiniteScroll = () =&amp;gt; {
    // initialize list of posts
    const [postList, setPostList] = useState({
        list: [1,2,3,4]
    }); 


    return (&amp;lt;div className="container" style={containerStyle}&amp;gt;
        &amp;lt;div className="post-list"&amp;gt;
            {
                postList.list.map((post, index) =&amp;gt; {
                    return (&amp;lt;div key={index} 
                             className="post" 
                             style={divStyle}&amp;gt;
                        &amp;lt;h2&amp;gt; {post } &amp;lt;/h2&amp;gt;
                    &amp;lt;/div&amp;gt;)
                })
            }
            &amp;lt;div className="loading"&amp;gt;
                    &amp;lt;h2&amp;gt;Load More&amp;lt;/h2&amp;gt;
           &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;)
}

export default InfiniteScroll;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Your page will now look like this:&lt;/strong&gt;&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Adding infinite scroll
&lt;/h2&gt;

&lt;p&gt;For this we would use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API" rel="noopener noreferrer"&gt;&lt;strong&gt;Interaction Observer API&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
Intersection Observer is a really awesome JavaScript API that simplifies scroll-based events in JavaScript. Rather than constantly checking the distance from the top, Intersection Observer watches when an element enters or exits the viewport.&lt;/p&gt;

&lt;p&gt;We will use interaction Observer to watch when user enters specific point and then load more posts.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;First we will import **useRef&lt;/em&gt;* and &lt;strong&gt;useEffect&lt;/strong&gt; hook from React and attach them to Load More div*&lt;/li&gt;
&lt;li&gt;&lt;em&gt;then will register IntersectionObserver on Load More div when component is mounted&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;add new state variable page, that will track on what page we currently are. To simulate more real life example how we would do it when connecting with backend&lt;/em&gt; &lt;/li&gt;
&lt;li&gt;&lt;em&gt;the last step when page is update, simply just load more posts&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Here is a complete code:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useEffect, useState, useRef  } from 'react';

const divStyle = {
    color: 'blue',
    height: '250px',
    textAlign: 'center',
    padding: '5px 10px',
    background: '#eee',
    marginTop: '15px'
};


const containerStyle = {
    maxWidth: '1280px',
    margin: '0 auto',
}
const InfiniteScroll = () =&amp;gt; {
    const [postList, setPostList] = useState({
        list: [1,2,3,4]
    }); 
    // tracking on which page we currently are
    const [page, setPage] = useState(1);
    // add loader refrence 
    const loader = useRef(null);

    useEffect(() =&amp;gt; {
         var options = {
            root: null,
            rootMargin: "20px",
            threshold: 1.0
         };
        // initialize IntersectionObserver
        // and attaching to Load More div
         const observer = new IntersectionObserver(handleObserver, options);
         if (loader.current) {
            observer.observe(loader.current)
         }

    }, []);


    useEffect(() =&amp;gt; {
        // here we simulate adding new posts to List
        const newList = postList.list.concat([1,1,1,1]);
        setPostList({
            list: newList
        })
    }, [page])

    // here we handle what happens when user scrolls to Load More div
   // in this case we just update page variable
    const handleObserver = (entities) =&amp;gt; {
        const target = entities[0];
        if (target.isIntersecting) {   
            setPage((page) =&amp;gt; page + 1)
        }
    }


    return (&amp;lt;div className="container" style={containerStyle}&amp;gt;
        &amp;lt;div className="post-list"&amp;gt;
            {
                postList.list.map((post, index) =&amp;gt; {
                    return (&amp;lt;div key={index} className="post" style={divStyle}&amp;gt;
                        &amp;lt;h2&amp;gt; {post } &amp;lt;/h2&amp;gt;
                    &amp;lt;/div&amp;gt;)
                })
            }
             &amp;lt;!-- Add Ref to Load More div --&amp;gt;
            &amp;lt;div className="loading" ref={loader}&amp;gt;
                    &amp;lt;h2&amp;gt;Load More&amp;lt;/h2&amp;gt;
           &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;)
}

export default InfiniteScroll;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is my first post on Dev.to Thank you for reading :)&lt;/p&gt;

&lt;p&gt;If you liked this post, you can find more by:&lt;/p&gt;

&lt;p&gt;Following me on Twitter:&lt;/p&gt;

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