web-dev-qa-db-fra.com

React Native ne peut pas accéder à this.props en dehors de la méthode render ()

J'essaie d'accéder à this.props dans la méthode clicked(), mais ils ne sont pas définis. Comment puis-je accéder à this.props à l'aide des méthodes de la classe ListItemExample? 

Mon objectif est de conserver la id dans la vue show qui montre la vue de détail d'un ListItemExample cliqué. 

export default class Example extends Component {

  constructor() {
    super();
    let ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});

    this.state =  {
      dataSource: ds,
      isLoading: true
    };
  }

  componentDidMount() {
    this.fetchData()
  }

  fetchData() {

    Api.getPosts().then((resp) => {
      console.log(resp);
      this.setState({
        dataSource: this.state.dataSource.cloneWithRows(resp.posts),
        isLoading: false
      })
    });

  }

  render() {
    return (
      <View style={styles.container}>

          <ListView
              dataSource={this.state.dataSource}
              renderRow={this.renderRow.bind(this)}
              style={styles.postList}
              />

      </View>
    );
  }

  renderRow(post) {
    return (
        <PostListItem
          id={post.id}
          coverImage={post.cover_image}
          title={post.title}
          lockedStatus={post.status}
          time={post.time} />
    );
  }

}



export default class ListItemExample extends Component {

  constructor() {
    super();
  }

  render() {
    return (
      <TouchableHighlight onPress={this.clicked} >
        <View style={styles.postItem}>


        </View>
      </TouchableHighlight>
    );
  }

  clicked() {
    console.log("clicked props");
    console.log(this.props);
    Actions.openPost();
  }

}
17
botbot

Vous devez faire onPress={this.clicked.bind(this)}

27
fandro

Avec le passage de React de createClass à ES6 classes, nous devons gérer la valeur correcte de this à nos méthodes, comme indiqué ici: http://www.newmediacampaigns.com/blog/refactoring-react-components-to -es6-classes Modifiez votre code pour que la méthode soit liée à la valeur correcte de this dans le constructeur en utilisant this.clicked = this.clicked.bind(this) dans votre constructeur.

Le no autobinding était une étape délibérée des gars de React pour les classes ES6. La liaison automatique pour corriger le contexte a été fournie avec React.createClass. Vous trouverez des détails à ce sujet ici: https://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html#autobinding

Donc, sur cette base, vous pouvez également changer votre méthode clicked en tant que:

export default class ListItemExample extends Component {

 constructor(props) {
   super(props);
 }

 render() {
   return (
    <TouchableHighlight onPress={this.clicked} >
      <View style={styles.postItem}>


      </View>
    </TouchableHighlight>
  );
 }

 clicked = () => {
   console.log("clicked props");
   console.log(this.props);
   Actions.openPost();
 }

}
8
Aditya Singh

Ajoutez bind(this) pour lier votre méthode au composant actuel, comme 

yourMethod(){
    console.log(this.props)
}    

<SomeComponent onClick={this.yourMethod.bind(this)} />
7

Vous pouvez utiliser les fonctions de flèche pour vos gestionnaires et vous lier automatiquement à la portée lexicale. ... ou descendez le traditionnel .bind (this) au moment de l'invocation ou dans votre constructeur. Mais notez bien qu’une réponse utilise cette approche: vous devez modifier vos paramètres Babel et vous assurer que vous avez "facultatif": ["es7.classProperties"] pour que les fonctions de flèche des classes fonctionnent correctement.

1
Ooki Koi

J'ai eu le même problème lors de l'utilisation de FBSDK avec React Native. Et @fandro answer a presque expliqué beaucoup de choses.

J'ai eu ceci:

render() {
        const infoRequest = new GraphRequest(
            '/me',
            null,
            this.responseInfoCallback,
        );

        return (
            <View>
                <LoginButton
                    readPermissions={["email"]}
                    onLoginFinished={
                        (error, result) => {
                            if (error) {
                                console.log("Login failed with error: " + result.error);
                            } else if (result.isCancelled) {
                                console.log("Login was cancelled");
                            } else {
                                new GraphRequestManager().addRequest(infoRequest).start(1000);
                                console.log("Login was successful with permissions: " + result.grantedPermissions)
                            }
                        }
                    }
                    onLogoutFinished={() => alert("User logged out")}/>
            </View>
        );
    }

responseInfoCallback(error, result) {
        if (error) {
            alert('Error fetching data: ' + error.toString());
        } else {
            alert('Success fetching data: ' + result.toString());
            this.props.onLoginSuccess();
        }
    }

Et l’appel de this.props.onLoginSuccess() a causé le problème "undefined n’est pas un objet évaluant this.props.onLoginSuccess ()". Donc, quand j'ai changé le code dans const infoRequest = new GraphRequest(...) pour inclure .bind(this):

const infoRequest = new GraphRequest(
        '/me',
        null,
        this.responseInfoCallback.bind(this),
    );

Ça a marché. J'espère que cela t'aides.

0
Array