0
votes

The issue:

ESLint is emitting a "X is assigned a value but never used. eslint(no-unused-vars)" error in VSCode:

no-unused-vars

no-unused-vars rule.

But the variable is being referenced inside this jsx part: enter image description here

I added the rules that should tell eslint to behave correctly when it comes to JSX: (.eslintrc.json part)

  "extends": [
    "eslint:recommended",
    "plugin:react/recommended",
    "plugin:import/errors",
    "plugin:jsx-a11y/recommended",
    "plugin:react-hooks/recommended",
    "prettier",
    "prettier/react"
  ],
  "plugins": ["react", "import", "jsx-a11y", "react-hooks"],
  "rules": {
    "react/prop-types": 0,
    "react/jsx-uses-react": 1,
    "react/jsx-uses-vars": 1,
    "no-console": 1,
    "react-hooks/rules-of-hooks": "error",
    "react-hooks/exhaustive-deps": "warn"
  },

Relevant data:

The React component...

import React, { useState } from 'react';
import { ANIMALS as kANIMALS } from '@frontendmasters/pet';

const SearchParams = () => {
  const [location, setLocation] = useState('Seattle, WA');
  const [animal, setAnimal] = useState('Animal');

  return (
    <div className="search-params">
      <form>
        <h1>{location}</h1>
        <label htmlFor="">
          Location
          <input
            id="location"
            type="text"
            value={location}
            placeholder="Location"
            onChange={(evt) => setLocation(evt.target.value)}
          />
        </label>
        <label htmlFor="animal">
          <select
            name="animal"
            id="animal"
            onBlur={(evt) => setAnimal(evt.target.value)}
          >
            <option value="All">All</option>
            {kANIMALS.map((animal) => (
              <option key={animal} value={animal}>
                {animal}
              </option>
            ))}
          </select>
        </label>
        <button>Submit</button>
      </form>
    </div>
  );
};

export default SearchParams;

the .eslintrc.json file

import React, { useState } from 'react';
import { ANIMALS as kANIMALS } from '@frontendmasters/pet';

const SearchParams = () => {
  const [location, setLocation] = useState('Seattle, WA');
  const [animal, setAnimal] = useState('Animal');

  return (
    <div className="search-params">
      <form>
        <h1>{location}</h1>
        <label htmlFor="">
          Location
          <input
            id="location"
            type="text"
            value={location}
            placeholder="Location"
            onChange={(evt) => setLocation(evt.target.value)}
          />
        </label>
        <label htmlFor="animal">
          <select
            name="animal"
            id="animal"
            onBlur={(evt) => setAnimal(evt.target.value)}
          >
            <option value="All">All</option>
            {kANIMALS.map((animal) => (
              <option key={animal} value={animal}>
                {animal}
              </option>
            ))}
          </select>
        </label>
        <button>Submit</button>
      </form>
    </div>
  );
};

export default SearchParams;

the package.json dependencies

  "devDependencies": {
    "eslint": "^7.1.0",
    "eslint-config-prettier": "^6.11.0",
    "eslint-plugin-import": "^2.20.2",
    "eslint-plugin-jsx-a11y": "^6.2.3",
    "eslint-plugin-react": "^7.20.0",
    "eslint-plugin-react-hooks": "^4.0.2",
    "parcel-bundler": "^1.12.4",
    "prettier": "^2.0.5"
  },
  "dependencies": {
    "@frontendmasters/pet": "^1.0.3",
    "react": "^16.13.1",
    "react-dom": "^16.13.1"
  }
1

1 Answers

3
votes

ESLint complains that a local state variable is never used no-unused-vars

The scope of the animal inside the map() is different to that of the animal state variable.

const [animal, setAnimal] = useState('Animal'); // state variable (component scope)

vs.

{kANIMALS.map((animal) => (
  <option key={animal} value={animal}> // map scope
    {animal}
  </option>
))}

This is commonly known as variable shadowing and can be detected via no-shadow rule.