2017-08-17 1 views
0

J'utilise Reactstrap dans mon projet d'intégration Bootstrap. Cependant, j'ai également besoin d'étendre le comportement onClick du composant Button qui sort de la boîte avec Reactstrap. À cette fin, j'ai fait un composant personnalisé NanoButton qui recompose le composant par défaut. Voici comment je l'appeler:"Impossible de lire la propriété 'onClick' de undefined" dans le composant React

<NanoButton type="button" onClick={() => Router.push('/about')}>About</NanoButton> 

Le composant NanoButton, comme je l'ai dit, ajoute ma fonctionnalité personnalisée onClick à la classe Button existante:

import { Component } from 'react'; 
import { Button } from 'reactstrap'; 

class NanoButton extends Component { 
    constructor(props) { 
    super(props); 
    this.onClick = this.onClick.bind(this); 
    } 
    onClick(e) { 
     var circle = document.createElement('div'); 
     e.target.appendChild(circle); 
     var d = Math.max(e.target.clientWidth, e.target.clientHeight); 
     circle.style.width = circle.style.height = d + 'px'; 
     var rect = e.target.getBoundingClientRect(); 
     circle.style.left = e.clientX - rect.left -d/2 + 'px'; 
     circle.style.top = e.clientY - rect.top - d/2 + 'px'; 
     circle.classList.add('ripple'); 

     this.props.onClick(); 
    } 
    render() { 
    return (
     <Button 
     className={this.props.className} 
     type={this.props.type} 
     color={this.props.color} 
     size={this.props.size} 
     onClick={this.onClick} 
     > 
     {this.props.children} 
     </Button> 
    ); 
    } 
} 

export default NanoButton; 

Comme vous pouvez le voir, j'ai besoin NanoButton composant pour effectuer certaines activités personnalisées avant d'exécuter la fonction onClick qui lui a été transmise en tant que prop. Mais lors du chargement dans le navigateur, il échoue à this.props.onClick(); en disant qu'il ne peut pas lire onClick on undefined? Que pourrais-je manquer ici?

Répondre

2

Votre méthode onClick n'est pas liée à votre contexte de classe et n'a donc pas accès à this.props.

La solution habituelle est de lier cette méthode dans votre constructeur:

constructor(props) { 
    super(props); 
    this.onClick = this.onClick.bind(this); 
} 

Une autre option consiste à lier dans le render comme il a été suggéré, mais cela signifie que la liaison se fera à chaque rendu, au lieu de n'utiliser qu'une seule fois la solution du constructeur.

+0

Voir mon commentaire à la réponse précédente. – TheLearner

+0

Je comprends ce que vous essayez de faire, et cela devrait fonctionner, le problème vient ici de la ligne 'this.props.onClick();' dans la méthode onClick, puisque cette méthode n'est pas liée à la classe, 'this. les accessoires »n'est pas défini. –

+0

Mais si je le lie, seul onClick est passé comme les accessoires s'exécuteront et celui défini dans le composant sera ignoré.Ce n'est pas ce que je cherche. J'ai besoin d'exécuter le onClick défini dans NanoButton ** avant ** d'exécuter le onClick qui lui est passé comme accessoire. – TheLearner

0

si vous voulez oublier quand lier ou non vos méthodes que vous pouvez remplacer le style suivant:

onClick(e) { 

} 

avec:

onClick = (e) => { 
    this.props.onClick(); 
} 

et la fonction de flèche lier automatiquement tout pour vous , vous n'avez pas besoin de modifier votre code uniquement de la façon dont vous définissez ces méthodes.

La raison de l'erreur onClick on undefined est que, en effet, onClick est défini dans la portée de l'élément Dom qui n'a pas la définition de la méthode onClick.

+0

J'ai besoin d'exécuter à la fois onClick et la liaison ne le fait pas accomplir cela. Si je voulais juste exécuter this.props.onClick, je le passerais simplement comme un accessoire à

+0

mettre un débogueur et inspecter la variable 'this' devrait être votre composant de classe React, honnêtement, je pense qu'il vous manque quelque chose dans votre code, ce code autorisé à exécuter du code et ensuite déclencher le rappel, je l'utilise tout le temps. – ncubica

0

Cela se produit lorsque this ne définit pas la fonction contexte, donc pour résoudre ce Il vous suffit de lier cette action, donc pour le faire, vous pouvez lier ce soit dans votre méthode constructeur ou vous pouvez lier directement cela avec la fonction chaque fois qu'elle est passée comme accessoire dans la fonction de rendu.

Reliure directement dans le constructeur

constructor(props){ 
super(props); 
this.onClick = this.onClick.bind(this); 
} 

En passant comme un des accessoires: -

<Button onClick={this.onClick.bind(this)/>