React Native не может получить доступ к this.props вне метода render()

Я пытаюсь получить доступ к this.props в методе clicked(), но они undefined. Как я могу получить доступ к this.props с помощью методов класса ListItemExample?

Моя цель - сохранить id в представлении представления, которое отображает подробное представление для щелчка 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();
  }

}

Ответ 1

Вам нужно сделать: onPress = {this.clicked.bind(this)}

Ответ 2

При смещении React от createClass до ES6 classes нам нужно обрабатывать правильное значение this для наших методов самостоятельно, как указано здесь: http://www.newmediacampaigns.com/blog/refactoring-react-components-to-es6-classes Измените свой код, чтобы метод был ограничен, чтобы исправить значение этого в конструкторе, используя this.clicked = this.clicked.bind(this) в вашем конструкторе

no autobinding был преднамеренным шагом от ребят Реагента для классов ES6. Автообъект для правильного контекста был предоставлен React.createClass. Подробности можно найти здесь: https://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html#autobinding

Таким образом, на основе этого вы также можете изменить свой метод clicked следующим образом:

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

}

Ответ 3

Добавьте bind(this) к привязке вашего метода к текущему компоненту, например

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

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

Ответ 4

У меня была такая же проблема при использовании FBSDK с React Native. И ответ @fandro почти многое объяснил.

У меня было это:

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

И вызов this.props.onLoginSuccess() вызванной проблемы "undefined не является объектом, оценивающим this.props.onLoginSuccess()". Поэтому, когда я изменил код в const infoRequest = new GraphRequest(...), включив .bind(this):

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

Это сработало. Надеюсь, это поможет.

Ответ 5

Вы можете использовать функции стрелок для ваших обработчиков и автоматически связываться с лексической областью.... или спуститесь по традиционному .bind(это) во время вызова или в ваш конструктор. Но обратите внимание, так как я думаю, что один из ответов использует этот подход: вы должны изменить настройки вашего Babel и убедиться, что у вас есть "необязательный": [ "es7.classProperties" ] для функций стрелок в классах для правильной работы.