2017-09-30 4 views
0

Je suis conscient des limites de JavaScript, mais je ne les comprends probablement pas entièrement car ce code ne fonctionne pas.Quelle est la raison pour laquelle cette fonction n'est pas transmise à un bouton?

Ce code utilise les frameworks React et Relay Modern.

Il y a 2 boutons, le premier à l'intérieur queryRender qui est passé dans le relais moderne QueryRenderer et le second ensuite (voir la fonction render). Le second fonctionne, le premier n'exécute pas la fonction clickTest. (ceci est une version simplifiée du code réel)

class Candidates extends Component { 
    static propTypes = { 
    viewer: PropTypes.object 
    } 

    constructor (props) { 
    super(props) 
    this.clickTest = this.clickTest.bind(this) 
    } 

    clickTest() { 
    console.log('click works') 
    }  

    queryRender ({error, props}) { 
    if (error) { 
     return <pre>{error.message}</pre> 
    } else if (props) { 
     return (
     <div> 
      <Button onClick={this.clickTest}>this DOESN'T work</Button> 
     </div> 
    ) 
    } 
    return <Loader active>Loading...</Loader> 
    } 

    render() { 
    return (
     <div> 
     <QueryRenderer 
      environment={environment} 
      query={query} 
      render={this.queryRender} 
     /> 
     <Button onClick={this.clickTest}>this works</Button> 
     </div> 
    ) 
    } 
} 

La variable query est définie, je n'ai pas inclus dans cet extrait.

Quand je Substitue la fonction de premier bouton onClick avec un anonyme un

<Button onClick={() => this.clickTest()}>this DOESN'T work</Button> 

puis-je obtenir une telle erreur: Uncaught TypeError: _this2.clickTest est pas une fonction

Quelqu'un peut-il me expliquer pourquoi ce code se comporte comme il le fait?

Répondre

1

En javascript, le sens de this n'est pas déterminé lorsqu'une fonction est créé, mais quand il est invoquaient. Lorsque QueryRenderer appelle votre fonction queryRender, il ne sait pas qu'il doit l'invoquer dans le contexte de votre classe, donc this ne fera pas référence à ce à quoi vous pensez qu'il fait référence. Vous aurez besoin de lier votre fonction queryRender, un peu comme vous le faites avec votre fonction clicktest dans le constructeur, ou vous aurez besoin de re-concevoir queryRender de sorte qu'il n'a pas besoin d'une référence à this.

+0

Merci, je n'ai pas pensé à lier la fonction 'queryRender'. Cela a résolu mon problème. – Pawel

0

La fonction flèche ne crée pas de nouvelle étendue et sa portée contient le contexte d'exécution, dans ce cas, il s'agit de la zone QueryRenderer où vous n'avez pas cette fonction. Lorsque vous le passez comme fonction simple, la portée sera indéfinie ou non, je ne sais pas ce que fait Button à l'intérieur. Je n'ai pas utilisé Rely et je ne suis pas sûr que vous pouvez vous référer au composant de la méthode de rendu Rely.

1

Pour développer à la fois les réponses d'Artur et de Nicholas, vous devez soit bind() ceci ou utiliser une fonction fléchée pour vous assurer que this fait référence au composant lui-même. Vous avez déjà la méthode bind, voici un exemple de la fonction flèche qui supprime le besoin de lier car les fonctions flèches ne lient pas réellement cette valeur, elles utilisent plutôt leur portée parents ...

class Candidates extends Component { 
    static propTypes = { 
    viewer: PropTypes.object 
    } 

    constructor (props) { 
    super(props) 
    this.clickTest = this.clickTest.bind(this) 
    } 

    clickTest() { 
    console.log('click works') 
    }  

    queryRender = ({error, props}) => { 
    if (error) { 
     return <pre>{error.message}</pre> 
    } else if (props) { 
     return (
     <div> 
      <Button onClick={this.clickTest}>this DOESN'T work</Button> 
     </div> 
    ) 
    } 
    return <Loader active>Loading...</Loader> 
    } 

    render() { 
    return (
     <div> 
     <QueryRenderer 
      environment={environment} 
      query={query} 
      render={this.queryRender} 
     /> 
     <Button onClick={this.clickTest}>this works</Button> 
     </div> 
    ) 
    } 
} 
+0

Merci Mike S. C'est en fait une information très utile. – Pawel