1
votes

La case à cocher Réagir ne définit pas son état sur coché lors du clic sur l'étiquette

J'ai un problème en raison du fait que ma case à cocher personnalisée ne fonctionne pas, Je ne suis pas très familier avec React, et je ne trouve pas non plus de bon endroit pour en savoir plus. Pouvez-vous vérifier mon code et me dire ce que j'ai fait de mal?

    import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

class Checkbox extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      checked: false
    };
    this.handleChange = this.handleChange.bind(this);
    this.checkbox = React.createRef();
    this.handleClick = () => {
      this.checkbox.current.click();
    };
  }

  componentDidMount() {
    this.setState({'checked' : this.props.checked});
  }

  handleChange() {
    this.setState({'checked' : !this.state.checked});
  }

  render() {
    let {
      className,
      label,
      ...attributes
    } = this.props;

    const classes = classNames(
      'checkbox',
      className,
    );

    return (
      <div className={classes}>
        <input id="checkbox_1" type="checkbox" checked={this.state.checked} onChange={this.handleChange} {...attributes} ref={this.checkbox} />
        <label for="checkbox_1" className="checkbox-label" onClick={this.handleClick}>{label}</label>
      </div>
    );
  }
}

Checkbox.defaultProps = {
  checked: false,
  className: '',
  label: null
};

Checkbox.propTypes = {
  checked: PropTypes.bool,
  className: PropTypes.string,
  onClick: PropTypes.func,
  label: PropTypes.string
};

export default Checkbox;

Le problème est que ce composant n'est pas vérifié, mais si je règle l'état sur vrai, il ne décoche pas, si j'installe un journal de la console à handleChange ou handleClick, j'obtiens console.logged lorsque je clique, mais seulement pour le premier clic, je ne sais pas ce que cela signifie. Dans un autre article ici, j'ai indiqué que cela pourrait poser un problème lorsque je coche et décoche pour que je crée une boucle infinie, mais dans ce cas, je devrais avoir une boucle infinie de console.logs, je pense. Si mon code est totalement faux, n'hésitez pas à le modifier comme vous le souhaitez, mais si ce n'est pas trop compliqué, essayez de commenter les parties modifiées pour que je comprenne mieux ce qui se passe: D

Merci d'avance .


3 commentaires

Série de tutoriels recommandés pour React: youtube.com/…


Il semble que vous ayez déjà résolu le problème, mais j'ai expliqué pourquoi certaines choses étranges se produisent dans ma réponse. Vérifiez-le :)


Oui thaks, c'est ce dont j'avais besoin aussi, quelqu'un qui peut clarifier certaines choses, merci beaucoup pour cela: D


3 Réponses :


2
votes

Bienvenue dans stackoverflow :)

Je pense que votre problème réside dans

handleChange() {
  this.setState({'checked' : !this.state.checked});
}

Vous ne changez pas l'état mais souhaitez simplement le redéfinir avec la même valeur . Vous devriez être bien quand vous le changez en:

handleChange() {
  this.setState({'checked' : this.state.checked});
}

EDIT:

Donc le vrai problème au sujet de l'entrée qui ne passe pas de coché à non coché est de remettre {... attributes} à l'entrée. Cela semble être lié à la propriété "checked" qui interfère avec la valeur vérifiée par défaut de l'élément d'entrée.

De plus, vous devriez utiliser l'attribut htmlFor au lieu de pour lorsque vous travaillez avec react.


5 commentaires

Hmm il semble que cela n'a pas résolu le problème, je vais éditer ma question pour ne pas confondre les gens: D


J'ai appliqué vos choses à mon code et maintenant je vois quand je montre ma case à cocher (elle est cachée pour que je puisse la styliser à ma façon) je peux la vérifier et cela fonctionne correctement, maintenant je dois la lier correctement à l'étiquette pour qu'elle soit cochée clic sur l'étiquette: DI essaiera de le comprendre, mais j'aimerais que vous partagiez également des informations à ce sujet: D


J'ai découvert la chose suivante Quand je clique sur l'étiquette, cela ne vérifie pas, mais cela bascule la vérification (si l'étiquette est cochée, je ne peux pas cocher la case) Nous sommes donc sur quelque chose, également lorsque je coche chackbox, l'étiquette (qui est conçue pour être chackbox) interagit également (changements css pour l'étiquette: coché)


Je l'ai fait fonctionner, merci, j'ai supprimé htmlFor de l'étiquette et cela a fonctionné correctement


@ PatrykGąsior consultez ma réponse - vous n'avez pas vraiment besoin de supprimer htmlFor , vous pouvez l'utiliser pour remplacer l'événement onClick , qui est plus propre



-1
votes

C'est aussi un problème HTML, vous devez lier l'étiquette avec l'entrée pour qu'elles se déclenchent ensemble, voir la solution ci-dessous, cela peut également aider ( https://www.w3schools.com/tags/tag_label.asp )

<h1>checkbox demo</h1>

<input type="checkbox">
<label>I don't activate the checkbox</label>

<hr>

<input type="checkbox" id="checkbox_1">
<label for="checkbox_1">I activate the checkbox</label>

<hr>

<label>
	<input type="checkbox">
	I also activate the checkbox
</label>


1 commentaires

Je suppose que ce n'était pas le cas, le problème persiste, je modifierai ma question avec votre solution également.



1
votes

Le problème numéro un est que vous définissez un accessoire par défaut vérifié: false dans defaultProps , et cet accessoire est toujours défini sur le input via {... attributes} , donc vous écrivez toujours cette valeur sur false, c'est pourquoi les changements d'état ne font aucune différence.

Pour résoudre le problème, vous pouvez soit vous débarrasser de cet accessoire par défaut (et également vous débarrasser de la définition de l'état dans componentDidMount ), soit arrêter de lancer toutes les données attributs dans l'élément input par défaut. À vous de décider.

Vous devriez maintenant pouvoir voir la case cochée / décochée.

En ce qui concerne le changement de la propriété for en htmlFor sur l'élément label , cela liera en fait le label à l'élément input , vous n'aurez donc pas à implémenter le gestionnaire onClick pour le label . Donc, une fois que vous corrigez cette propriété, débarrassez-vous simplement de votre onClick sur le label entièrement. Voici le code final:

Dans l'ensemble, voici ce qu'il faut changer:

  1. Supprimer {... attributes} de l'élément ou supprimer coché de defaultProps
  2. Remplacez la propriété for par htmlFor sur l'élément
  3. Supprimez l'événement onClick de l'élément

4 commentaires

Merci pour les informations fournies, mais comme aller pour le numéro 2, j'ai testé cette solution et je crois qu'il n'est pas sage de l'utiliser en composant. Permettez-moi de vous expliquer pourquoi (corrigez-moi si je me trompe), lorsque j'utilise 2 de ces derniers, je dois leur attribuer des identifiants non identiques comme la case à cocher-1 case à cocher-2, etc. fait de manière dynamique, mais pour l'instant je ne pense pas que ce soit important pour moi: D peut-être plus tard quand j'optimiserai les choses, je penserai à cette solution


@ PatrykGąsior si vous craignez de devoir coder en dur le id correspondant dans le elem / htmlFor dans le elem, je recommanderais l'une des deux solutions suivantes: 1) Transmettez cette valeur comme accessoire, de sorte que le composant parent passe identifier = {'checkbox-1'} , puis utilisez this.props.identifier dans les composants et


Option 2: dans votre composant de classe Checkbox , lors de l'initialisation de l'état, créez une chaîne aléatoire (ou un nombre aléatoire) puis attachez-la à une chaîne, comme: this.state = {checked: false, identifiant: 'checkbox-' + ~~ (Math.random () * 10000)} , puis utilisez this.state.identifier dans votre et les composants .


@ PatrykGąsior dans l'option # 2, vous n'aurez plus à penser à transmettre quoi que ce soit à vos composants Checkbox , ils se synchroniseront automatiquement. Dans l'option n ° 1, vous le ferez, donc vous devrez probablement définir cet accessoire comme requis via PropTypes . Pensées?