<?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: Will Adams</title>
    <description>The latest articles on DEV Community by Will Adams (@bushblade).</description>
    <link>https://dev.to/bushblade</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%2F117510%2Ffe5cb7ff-7eaf-4637-8afe-d83995c03701.jpeg</url>
      <title>DEV Community: Will Adams</title>
      <link>https://dev.to/bushblade</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bushblade"/>
    <language>en</language>
    <item>
      <title>Why you should add Eslint to a React Vite project</title>
      <dc:creator>Will Adams</dc:creator>
      <pubDate>Tue, 11 Apr 2023 13:48:33 +0000</pubDate>
      <link>https://dev.to/bushblade/add-eslint-to-a-react-vite-project-4pib</link>
      <guid>https://dev.to/bushblade/add-eslint-to-a-react-vite-project-4pib</guid>
      <description>&lt;p&gt;&lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;Vite&lt;/a&gt; is an excellent build tool for React applications that offers near-instantaneous startup times and a plugin system, with a much nicer development experience than Create React App.&lt;/p&gt;

&lt;h2&gt;
  
  
  Coming from Create React App
&lt;/h2&gt;

&lt;p&gt;If you're coming from Create React App, you may be used to having many &lt;a href="https://eslint.org/" rel="noopener noreferrer"&gt;eslint&lt;/a&gt; plugins included out-of-the-box, like &lt;a href="https://www.npmjs.com/package/eslint-plugin-react-hooks" rel="noopener noreferrer"&gt;eslint-plugin-react-hooks&lt;/a&gt;,&lt;br&gt;
which helps enforce rules of React Hooks, utlimately keeping you on the right path in the use of hooks.&lt;br&gt;&lt;br&gt;
Since the new &lt;a href="https://react.dev" rel="noopener noreferrer"&gt;React Docs&lt;/a&gt; have been released with zero mention of &lt;a href="https://create-react-app.dev/" rel="noopener noreferrer"&gt;Create React App&lt;/a&gt; Vite is becoming a more popular option to get started, but out of the box it lacks some of the tooling which CRA offered.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example:
&lt;/h3&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%2Fres.cloudinary.com%2Fbushblade%2Fimage%2Fupload%2Fc_scale%2Cw_800%2Ff_webp%2Fbushbladedotdev%2Feslint-no-error.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%2Fres.cloudinary.com%2Fbushblade%2Fimage%2Fupload%2Fc_scale%2Cw_800%2Ff_webp%2Fbushbladedotdev%2Feslint-no-error.png" alt="No errors"&gt;&lt;/a&gt;&lt;br&gt;
Here we are clearly breaking the &lt;a href="https://legacy.reactjs.org/docs/hooks-rules.html" rel="noopener noreferrer"&gt;rules of hooks&lt;/a&gt;, we are trying to use &lt;a href="https://react.dev/reference/react/useEffect" rel="noopener noreferrer"&gt;useEffect&lt;/a&gt; inside a functtion and returning a Promise that resolves with &lt;code&gt;'foo'&lt;/code&gt; &lt;strong&gt;You cannot and should not do this.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Fortunately, it's easy to add these plugins to Vite as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install eslint and necessary plugins
&lt;/h2&gt;

&lt;p&gt;First, install eslint and any necessary plugins as development dependencies using our package manager of choice (&lt;a href="https://pnpm.io/" rel="noopener noreferrer"&gt;pnpm for me&lt;/a&gt;):&lt;/p&gt;

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

pnpm i &lt;span class="nt"&gt;-D&lt;/span&gt; eslint eslint-plugin-react eslint-plugin-react-hooks



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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Create an eslint configuration file
&lt;/h2&gt;

&lt;p&gt;Create an &lt;a href="https://eslint.org/docs/latest/use/configure/configuration-files" rel="noopener noreferrer"&gt;eslint configuration file&lt;/a&gt;, in the root of our project. Here's an example configuration that extends the recommended eslint rules and includes the necessary plugins:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: You can use json, yaml or a JavaScript file for our &lt;br&gt;
eslint config.  &lt;/p&gt;

&lt;p&gt;Here we'll go with json.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Name the file &lt;strong&gt;.eslintrc.json&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"extends"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"eslint:recommended"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"plugin:react/recommended"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"plugin:react-hooks/recommended"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"plugins"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"react"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-hooks"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"parserOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ecmaVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2020&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"sourceType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ecmaFeatures"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"jsx"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"browser"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"es2020"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"react/react-in-jsx-scope"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"off"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


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

&lt;/div&gt;

&lt;p&gt;This configuration extends the recommended eslint rules and adds the necessary plugins for &lt;strong&gt;React&lt;/strong&gt; and &lt;strong&gt;React Hooks&lt;/strong&gt;. It also enables parsing of jsx syntax and sets up the environment to include the browser and es2020. This may be all you need and if you have a eslint plugin in our editor, you&lt;br&gt;
should start now seeing output in our editor from the linter if you do something you should not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add eslint to Vite
&lt;/h2&gt;

&lt;p&gt;Now that eslint is configured we can add a plugin for Vite so you can get the linting to run at build time to check our code before you deploy. The plugin also runs eslint with output into our browser console, so you really have no excuse for ignoring the warnings!&lt;/p&gt;

&lt;p&gt;install the &lt;strong&gt;vite-plugin-eslint&lt;/strong&gt; plugin:&lt;/p&gt;

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

pnpm i &lt;span class="nt"&gt;-D&lt;/span&gt; vite-plugin-eslint


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

&lt;/div&gt;

&lt;p&gt;Then, add the following to our &lt;strong&gt;vite.config.js&lt;/strong&gt; file:&lt;/p&gt;


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

&lt;p&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;br&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;react&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;@vitejs/plugin-react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;br&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;eslintPlugin&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vite-plugin-eslint&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;br&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;br&gt;
    &lt;span class="nf"&gt;react&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;br&gt;
    &lt;span class="nf"&gt;eslintPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;cache&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;br&gt;
      &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/&lt;strong&gt;/*.js&lt;/strong&gt;&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;./src//*.jsx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;exclude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;&lt;br&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;&lt;br&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;&lt;br&gt;
&lt;span class="p"&gt;})&lt;/span&gt;&lt;/p&gt;

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

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Check it's all working&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;If we take a look back out our code from earlier, we should now see some warnings and errors from the linter&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%2Fres.cloudinary.com%2Fbushblade%2Fimage%2Fupload%2Fc_scale%2Cw_800%2Ff_webp%2Fbushbladedotdev%2Feslint-error-react-vite.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%2Fres.cloudinary.com%2Fbushblade%2Fimage%2Fupload%2Fc_scale%2Cw_800%2Ff_webp%2Fbushbladedotdev%2Feslint-error-react-vite.png" alt="Eslint showing errors"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Much better!&lt;/strong&gt; Adding eslint to our Vite React project and extending the necessary plugins, ensures that our code adheres to best practices and coding standards.&lt;br&gt;
Eslint is a powerful tool that can help you catch issues early in development, saving you time and effort in the long run.&lt;br&gt;
If you're starting out on your React journey and using Vite, I highly recommend using Eslint to help you learn how to use hooks correctly.&lt;/p&gt;

</description>
      <category>react</category>
      <category>vite</category>
      <category>eslint</category>
    </item>
  </channel>
</rss>
