2017-04-09 1 views
3

Bonjour je tentais de passer fonction à la classe de l'enfant et l'appeler de la classe des enfants, mais le problème, il montre la fonction est définieComment appeler la fonction parent d'un enfant prop RÉAGIR 15.5.0

Impossible de lire propriété 'removeComment' undefined

ici est mes codes

classe parente:

import React from 'react'; 
import Navbar from './notes'; 

export default class Board extends React.Component { 
    constructor(props, context) { 
     super(props, context); 
     this.state = { 
      comments: [ 
       'Kingyyy', 
       'React', 
       'Learning' 
      ] 
     }; 
    } 
    removeComment() { 
     console.log(i); 
     var arr = this.state.comments; 
     arr.splice(i,1); 
     this.setState({comments: arr}); 
    } 
    editComment(newtext, i) { 
     console.log(i); 
     var arr = this.state.comments; 
     arr[i] = newtext; 
     this.setState({comments: arr}); 
    } 
    addComment() { 
     var text = prompt('enter the new '); 
     var arr = this.state.comments; 
     arr[arr.length] = text; 
     this.setState({comments: arr}); 
    } 
    eachComment(elem, i) { 
     return (
      <Navbar key={i} index={i} editComment={(newtext, i) => this.editComment.bind(this)} removeComment={(i) => this.removeComment.bind(this)}> 
       {elem} 
      </Navbar> 
     ); 
    } 
    render() { 
     return (
      <div> 
      <button onClick={this.addComment} className="btn btn-success">add new comment</button> 
      <br /> 
       { 
        this.state.comments.map(this.eachComment) 
       } 
      </div> 
     ); 
    } 
} 

la classe enfant:

import React from 'react'; 

export default class Navbar extends React.Component { 
    edit() { 
     this.setState({ 
      edit: !this.state.edit 
     }) 
    } 
    save() { 
     var value = this.refs.newtext.value; 
     this.props.editComment(value,this.props.index); 
     this.setState({ 
      edit: !this.state.edit 
     }) 
    } 
    remove() { 
     this.props.removeComment(this.props.index); 
    } 
    constructor(props, context) { 
     super(props, context); 
     this.state = {edit: false}; 
    } 
    normal() { 
     return (
      <div> 
       <h1>{this.props.children}</h1> 
       <button className="btn btn-info" onClick={this.edit.bind(this)}> 
        edit 
       </button> 
       <button className="btn btn-danger" onClick={this.remove.bind(this)}> 
        remove 
       </button> 
      </div> 
     ); 
    } 
    editing() { 
     return (
      <div> 
       <textarea ref="newtext" defaultValue={this.props.children}></textarea> 
       <br/> 
       <button className="btn btn-success" onClick={this.save.bind(this)}> 
        save 
       </button> 

      </div> 
     ); 
    } 
    render() { 
     if (this.state.edit) { 
      return this.editing(); 
     } else { 
      return this.normal(); 
     } 
    } 
} 

Répondre

2

le problème est que vous perdez votre réaction contexte. Changer votre constructeur de la classe enfant à cette

constructor(props, context) { 
    super(props, context); 
    this.state = {edit: false}; 
    this.normal = this.normal.bind(this) 
    this.editing = this.editing .bind(this) 
} 

vous appelez .bind (cela) sur votre appel SUPPRIMER ... mais le this vous liez ne pas le contexte réagir avec l'état et les accessoires

quelques optimisations je suggère ..

définissent vos fonctions inline lambdas de sorte que vous ne devez pas appeler .bind (cela) sur chaque fonction à chaque fois ... autre titre:

edit =() => { 
    this.setState({ 
     edit: !this.state.edit 
    }) 
} 
save =() => { 
    var value = this.refs.newtext.value; 
    this.props.editComment(value,this.props.index); 
    this.setState({ 
     edit: !this.state.edit 
    }) 
} 
remove =() => { 
    this.props.removeComment(this.props.index); 
} 
normal =() => { 
    return (
     <div> 
      <h1>{this.props.children}</h1> 
      <button className="btn btn-info" onClick={this.edit}> 
       edit 
      </button> 
      <button className="btn btn-danger" onClick={this.remove}> 
       remove 
      </button> 
     </div> 
    ); 
} 
editing =() => { 
    return (
     <div> 
      <textarea ref="newtext" defaultValue={this.props.children}></textarea> 
      <br/> 
      <button className="btn btn-success" onClick={this.save}> 
       save 
      </button> 

     </div> 
    ); 
} 

dans la classe parente changez la façon dont vous passez les fonctions. Essayez toujours d'éviter les lambdas en ligne comme propriétés sur un élément ou sur une classe de réaction (dans le rendu). Cela entraînera des problèmes de performances au fur et à mesure que le site deviendra plus complexe.

eachComment = (elem, i) => { 
    return (
     <Navbar key={i} index={i} editComment={this.editComment} removeComment={this.removeComment}> 
      {elem} 
     </Navbar> 
    ); 
} 

si vous avez besoin de passer des variables personnalisées à une fonction qui ont été définis, vous pouvez utiliser en ligne .bind pour les passer à travers au lieu d'un lambda (bind est beaucoup plus performant qu'un lambda ... autre titre:

someList.map((item, i) => <SomeElement onUserClick={this.handleUserClick.bind(null, item) />); 

premier argument de .bind() est le contexte this vous pouvez passer null à ne pas passer outre le contexte. et vous pouvez passer d'autres arguments à la fonction des arguments étendus sur l'appel invoqué.

+0

Merci pour la réponse mais c'est le même problème lem et la même erreur "Impossible de lire la propriété 'removeComment' de undefined" –

+0

Les accessoires ne sont pas définis. vous devez vous assurer que votre fonction a ce contexte. lier à toutes vos fonctions –

+0

cela a fonctionné après que j'ajoute ceci "this.eachComment = this.eachComment.bind (this);" au constructeur parent merci –