简体   繁体   中英

React Native can't access this.props outside of render() method

I am trying to access this.props in the clicked() method, but they are undefined. How can I access this.props through the methods in the ListItemExample class?

My goal is to maintain the id into the show view that shows the detail view for a clicked ListItemExample.

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();
  }

}

你需要做onPress={this.clicked.bind(this)}

With the shift of React from createClass to ES6 classes we need to handle the correct value of this to our methods on our own, as mentioned here: http://www.newmediacampaigns.com/blog/refactoring-react-components-to-es6-classes Change your code to have the method bounded to correct value of this in constructor using this.clicked = this.clicked.bind(this) in your constructor

The no autobinding was a deliberate step from React guys for ES6 classes. Autobinding to correct context was provided with React.createClass . Details of this can be found here: https://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html#autobinding

So based on this you could also change your clicked method as:

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();
 }

}

Add bind(this) to binding your method into current component, like

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

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

I had same issue when using FBSDK with React Native. And @fandro answer almost did explain a lot.

I had this:

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();
        }
    }

And call of this.props.onLoginSuccess() caused issue "undefined is not an object evaluating this.props.onLoginSuccess()". So when I changed the code in const infoRequest = new GraphRequest(...) to include .bind(this) :

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

It worked. Hope this helps.

You can use arrow functions for your handlers and bind to the lexical scope automagically. ... or go down the traditional .bind(this) at invocation time or in your constructor. But note, as I think one answer uses this approach: you must change your babel settings and ensure you have "optional": ["es7.classProperties"] for arrow functions in classes to work properly.

In then compnent that you're trying enter to another view you must send the object navigation by you use this in the onPress of component imported

example

Implementing component in a view

<CardComponent title="bla bla" navigation={this.props.navigation} />

Component template

`<View>
       <Button  title={this.props.title} onPress={()=> 
       this.props.navigation.navigate("anotherAwesomeView")}/>
</View>`

This problem is because the component that you're trying implement is not defined on stackNavigation, and by this the methot navigation is not avalible for you, and passing this object navigator by params you'll can access to it

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM