82 votes

Évitez l'erreur eslint no-shadow avec mapDispatchToProps

J'ai le composant suivant qui déclenche une erreur ESlint no-shadow sur les props de FilterButton.

import { setFilter } from '../actions/filter';

function FilterButton({ setFilter }) {
  return (
    Click
  );
}

export default connect(null, { setFilter })(FilterButton);

Comment puis-je éviter l'avertissement tout en conservant à la fois la syntaxe concise de mapDispatchToProps et la règle ESlint ?

Je sais que je peux ajouter un commentaire pour supprimer l'avertissement mais le faire pour chaque composant semble redondant et fastidieux.

0 votes

Vous pouvez renommer setFilter (FilterButton({ setFilter }) en FilterButton({ setFilter })). Cela a du sens (en quelque sorte) car la fonction qui se trouve dans les proprétés de FilterButton est en réalité l'originale setFilter avec la fonction dispatch qui lui est liée.

0 votes

Avant et après le renommage sont les mêmes.

0 votes

Je voulais simplement renommer dans function FilterButton({ setFilter }) { et Cliquez. Pouvez-vous mettre à jour votre question avec le code modifié?

198voto

jabacchetta Points 2067

Il y a quatre options ici:

1. Désactiver la règle.

Pourquoi?

C'est la manière la plus simple d'éviter l'erreur ESLint.

Pourquoi pas?

La règle no-shadow aide à prévenir un bug très courant lors de l'utilisation de react-redux. C'est-à-dire, essayer d'invoquer l'action brute et non connectée (qui n'est pas automatiquement envoyée).

En d'autres termes, si vous n'utilisiez pas la destructuration et obteniez l'action des props, setFilter() n'enverrait pas l'action (car vous invoqueriez directement l'action importée, au lieu d'invoquer l'action connectée via les props avec props.setFilter(), que react-redux envoie automatiquement pour vous).

En nettoyant le masquage des variables, vous et/ou votre IDE êtes plus susceptibles de repérer l'erreur.

Comment?

Ajouter une propriété eslintConfig à votre fichier package.json est une manière de le faire.

"eslintConfig": {
    "rules": {
      "no-shadow": "off",
    }
  }

2. Réattribuer la variable lors de son passage dans connect().

Pourquoi?

Vous bénéficiez de la sécurité de la règle no-shadow, et, si vous choisissez de respecter une convention de nommage, cela devient très explicite.

Pourquoi pas?

Cela introduit du boilerplate.

Si vous n'utilisez pas de convention de nommage, vous devez maintenant trouver des noms alternatifs (qui ont toujours du sens) pour chaque action. Et il y a de fortes chances que les mêmes actions aient des noms différents d'un composant à l'autre, ce qui rend plus difficile de se familiariser avec les actions elles-mêmes.

Si vous utilisez une convention de nommage, les noms deviennent longs et répétitifs.

Comment?

Sans convention de nommage:

import { setFilter } from '../actions/filter';

function FilterButton({ filter }) {
  return (
    Cliquez
  );
}

export default connect(null, { filter: setFilter })(FilterButton);

Avec convention de nommage:

import { setFilter, clearFilter } from '../actions/filter';

function FilterButton({ setFilterConnect, clearFilterConnect }) {
  return (
    Cliquez
  );
}

export default connect(null, {
  setFilterConnect: setFilter,
  clearFilterConnect: clearFilter,
})(FilterButton);

3. Ne pas déstructurer les actions des props.

Pourquoi?

En utilisant explicitement la méthode du objet props, vous n'avez pas besoin de vous soucier du masquage au départ.

Pourquoi pas?

Précéder toutes vos actions de props/this.props est répétitif (et incohérent si vous déstructurez toutes vos autres props non-actions).

Comment?

import { setFilter } from '../actions/filter';

function FilterButton(props) {
  return (
    Cliquez
  );
}

export default connect(null, { setFilter })(FilterButton);

4. Importer l'ensemble du module.

Pourquoi?

C'est concis.

Pourquoi pas?

D'autres développeurs (ou votre futur moi) pourraient avoir du mal à comprendre ce qui se passe. Et en fonction du guide de style que vous suivez, vous pourriez enfreindre la règle no-wildcard-imports.

Comment?

Si vous envoyez simplement des créateurs d'actions d'un module:

import * as actions from '../actions/filter';

function FilterButton({ setFilter }) {
  return (
    Cliquez
  );
}

export default connect(null, actions)(FilterButton);

Si vous envoyez plusieurs modules, utilisez la déstructuration d'objet avec la syntaxe rest:

import * as filterActions from '../actions/filter';
import * as otherActions from '../actions/other';

// toutes les actions exportées des deux fichiers importés sont maintenant disponibles en tant que props
function FilterButton({ setFilter, clearFilter, setOther, clearOther }) {
  return (
    Cliquez
  );
}

export default connect(null, { ...filterActions, ...otherActions })(FilterButton);

Et comme vous avez mentionné une préférence pour la syntaxe concise d'ES6 dans les commentaires, autant ajouter la fonction fléchée avec un retour implicite :

import * as actions from '../actions/filter';

const FilterButton = ({ setFilter }) => Cliquez;

export default connect(null, actions)(FilterButton);

1 votes

Merci! Ceci devrait être la réponse acceptée pour sûr.

5 votes

Réponse très bien écrite. Bien que, il faut arrêter de lire après Désactiver la règle :)

0 votes

C'est ce type de réponse qui fait de SO une ressource exceptionnelle.

14voto

GollyJer Points 1108

Une cinquième option :

5. Autoriser une exception spécifique via les règles eslintrc.

module.exports = {
  rules: {
    'no-shadow': [
      'error',
      {
        allow: ['setFilter'],
      },
    ],
  }
}

Pourquoi ?

Vous ne voulez pas d'occultation de variables mais vous ne pouvez pas l'éviter dans certains cas.

Pourquoi pas ?

Vous ne voulez vraiment pas d'occultation de variables dans votre code source.

0 votes

J'aime cette option, mais elle ne fonctionne pas pour moi. Je vois toujours l'erreur

8voto

bpalij Points 151

Option numéro six.

6. Désactiver la règle es-lint pour la ou les lignes de code spécifiques

import { setFilter } from '../actions/filter';

// eslint-disable-next-line no-shadow
function FilterButton({ setFilter }) {
  return (
    Cliquez
  );
}

export default connect(null, { setFilter })(FilterButton);

ou

import { setFilter } from '../actions/filter';

/* eslint-disable no-shadow */
function FilterButton({ setFilter }) {
/* es-lint-enable */
  return (
    Cliquez
  );
}

export default connect(null, { setFilter })(FilterButton);

La deuxième façon de désactiver temporairement la règle es-lint peut être utilisée pour plusieurs lignes de code, contrairement à la première. Cela peut être utile si vous passez plus d'arguments et les divisez en plusieurs lignes de code.

Pourquoi ?

C'est une option facile et adaptée pour certains cas d'utilisation (par exemple, votre équipe/organisation utilise des réglages es-lint spécifiques et il est découragé/interdit de les modifier). Cela désactive l'erreur es-lint dans la ou les lignes de code mais n'influence pas la syntaxe mapDispatchToProps et la règle est toujours complètement active en dehors de la ou des lignes de code.

Pourquoi pas ?

Vous ne voulez pas ou il vous est interdit d'alourdir votre code avec ce type de commentaires. Vous ne voulez pas ou il vous est interdit d'influencer le comportement es-lint.

5voto

gqstav Points 1500

J'ai ajusté 4. et j'ai réussi à obtenir ce que j'aimerais appeler l'option 8.

8. Importez des méthodes sous un nom différent

Pourquoi?

Il offre les mêmes avantages qu'importer l'ensemble du module mais sans entrer en conflit avec d'autres règles, par exemple Ne pas utiliser d'imports de type wildcard (airbnb).

Pourquoi pas?

Cela ajoute une déclaration de variable inutile qui pourrait causer de la confusion.

Comment?

Pour le cas d'une seule méthode

import { setFilter as setFilterConnect } from '../actions/filter';

function FilterButton({ setFilter }) {
  return Cliquez;
}

export default connect(
  null,
  { setFilter: setFilterConnect }
)(FilterButton);

4voto

Mark Dreyer Points 94

Avec la nouvelle API Hooks ajoutée dans la version 7.1.0, vous pouvez vous débarrasser totalement de la variable et de mapDispatchToProps :

import { useDispatch } from 'react-redux'
import { setFilter } from '../actions/filter';

function FilterButton() {
  const dispatch = useDispatch()
  return (
    Cliquez
  );
}

export default FilterButton;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X