2017-10-20 16 views
0

J'ai plusieurs éléments avec la même className et je veux si un élément (avec className historique nœud) est cliqué, il devrait obtenir className actif avec className en cours.En passant seul élément cliqué à la fonction onClick - reactjs

Mais j'ai un problème, il y a des enfants de cet élément et si des éléments enfants sont cliqués, ils obtiennent également la classe Active.

Voici le code:

<div className="history-node-container" key={index}> 
    <div className="history-node" onClick={(e) => {this.handleHistoryClick(e.target)}}> 
    <span className="history-title">{heading.action}</span> 
    <span className="history-date">{moment(heading.added_at).format("MMMM Do, YYYY")}</span> 
    </div> 
</div> 

handleHistoryClick fonction

handleHistoryClick(target){ 
    $('.history-node').removeClass('active'); //removing active class from all elements 
    target.className = 'history-node active'; 
} 

Je veux exécuter la fonction lorsque l'utilisateur clique sur l'élément avec className historique nœud

Mais si l'utilisateur clique sur histoire-titre, ClickHandler donne classe actif à élément-historique élément.

COMPORTEMENT ATTENDU: si vous cliquez sur l'historique-nœud, seul l'historique-noeud doit avoir la classe active.

Répondre

3

Une astuce et comment résoudre votre problème (de deux manières)

Conseil: généralement pas la meilleure idée de mélanger React avec jQuery. React est venu comme un changement de paradigme majeur dans la façon dont nous interagissons avec le DOM. Essayez de lire un peu plus sur React, comment cela fonctionne, pourquoi est-il si différent de simplement ajouter/supprimer des éléments dans le DOM avec jQ.

Quelques références pour vous aider à cela:

How to go from jQuery to React.js?

Thinking in React for jQuery Programmers


Maintenant, revenir à votre question

Vous devez utiliser currentTarget.

Comme les .history-title et .history-date éléments sont enveloppés dans les .history-node, tout clic sur les déclenchera, il est l'événement de parent, puisque le corps est .history-node.history-title + .history-date. C'est le bon comportement. Lorsque vous déclenchez un événement dans JS, l'objet event reçoit deux paramètres: target, qui est l'événement déclenchant l'événement et currentTarget, l'élément qui écoute réellement l'événement.

maintenant le code:

avec JQ

Composant:

<div className="history-node-container" key={index}> 
    <div className="history-node" onClick={handleHistoryClick}> 
    <span className="history-title">{heading.action}</span> 
    <span className="history-date">{moment(heading.added_at).format("MMMM Do, YYYY")}</span> 
    </div> 
</div> 

Clics:

handleHistoryClick(event){ 
    $('.history-node').removeClass('active') 
    event.currentTarget.classList.add('active') 
} 

REACT façon (pure React, pas de modules)

Composant:

class HistoryNode extends Component { 
    constructor(props) { 
     super(props) 
     this.state = { isActive: false } 
     this.handleClick = this.handleClick.bind(this) 
    } 

    handleClick(e) { 
     let state = this.state 
     this.setState({isActive: !state.isActive}) 
    } 

    render() { 
     return(
     <div className="history-node-container"> 
      <div className={`history-node ${this.state.isActive ? 'active' : ''}`} onClick={handleHistoryClick}> 
      <span className="history-title">{heading.action}</span> 
      <span className="history-date"> 
       {moment(heading.added_at).format("MMMM Do, YYYY")}</span> 
      </div> 
     </div> 
    ) 
    } 
} 

Remarquez que vous n'avez pas besoin de manipuler le DOM à tout moment à la solution React. Vous attachez simplement votre événement à ce composant particulier, définissez comment son changement d'état devrait refléter sur l'interface utilisateur et laissez React faire le reste.

Hope it helps;)

Reference for target vs currentTarget

+1

Grande explication bien. Merci beaucoup pour votre temps et d'efforts. Je l'ai eu le travail –

+0

Vous êtes les bienvenus mec, content que cela a aidé –

1

Je pense que l'événement se propage aux composants enfants.

Avez-vous essayé?

<div className="history-node-container" key={index}> 
    <div className="history-node" onClick={handleHistoryClick}> 
    <span className="history-title">{heading.action}</span> 
    <span className="history-date">{moment(heading.added_at).format("MMMM Do, YYYY")}</span> 
    </div> 
</div> 

fonction HandleClick

handleHistoryClick(event){ 
    event.stopPropagation(); 
    $('.history-node').removeClass('active'); 
    event.target.className = 'history-node active'; 
} 

EDIT: Vous pouvez le rendre plus simple si (et sans jQuery) en utilisant votre état du composant. Mais sans savoir comment vous avez écrit votre composant je ne peux pas vous donner un extrait illustrant. Attention aussi lorsque vous interagissez directement avec le DOM, cela implique une perte de performance. L'utilisation de l'état React vous permet d'éviter une telle chose!

+0

Nop, il ne fonctionne pas. Le comportement est le même. :( –

+0

Pouvez-vous modifier votre message d'origine avec l'ensemble de la pièce? – 3Dos

+0

Eh oui, voici un [Paste] (https://pastebin.com/qcNk9nzY) –