Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass a component reference to onPress callback?

Tags:

react-native

I did render following kind of list with onPress "handler".

enter image description here

I have realised that onPress handler is useless because I cannot get the reference of race pressed. I get ref is not defined error.

var races = Engine.possibleRaces;

function racePressed(ref) {
    console.log("REF: " + ref); // is never called
}

var races = Engine.possibleRaces;
var rowViews = [];
for (var i = 0; i < races.length; i++) {
  rowViews.push(
    <Text
      ref={i}
      onPress={() => racePressed(ref)} // ref is not defined
      style={styles.raceText}>{races[i].text}
    </Text>

  );
}

<View style={{width: Screen.width, flexDirection:'row', flexWrap: 'wrap', alignItems: "center"}}>
       {rowViews}
</View>  

I did also try to pass i as a parameter. It did not work, because it has the value after iteration ends. Basically it has races.length value.

  onPress={() => racePressed(i)} // Same as races.length

Edit:

I did isolate problem to following program.

'use strict';
import React, {
  AppRegistry,
  Component,
  StyleSheet,
  Text,
  View
} from 'react-native';

let texts = [{text: "Click wrapper text1"}, {text: "Click wrapper text2"}];

class sandbox extends Component {

  rowPressed(ref, i) {
    console.log("rowPressed: " + ref + " " + i)
  }

  render() {

    var rows = [];

    for (var i = 0; i < texts.length; i++) {
      rows.push(
        <Text
          ref={i}
          onPress={() => this.rowPressed.bind(this, i)}
          style={styles.raceText}>{texts[i].text}
        </Text>
      );
    }

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

        <View>
          {rows}
        </View>

      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center'
  }
});

AppRegistry.registerComponent('sandbox', () => sandbox);

Callback is not called and no errors thrown except following warning

[tid:com.facebook.React.JavaScript] Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of `sandbox`. See https://fb.me/react-warning-keys for more information.
like image 441
Markku Avatar asked Feb 26 '16 23:02

Markku


2 Answers

I suggest you bind that function in constructor like..

constructor(props){
    super(props);
    //your codes ....

    this.rowPressed = this.rowPressed.bind(this);
}

This binds this context of rowPressed function as you expect it to be, making your code works properly.

Also, to get rid of warning messages you should provide unique key properties for each <Text> element, using <Text key={i} ....> in your code should work.

like image 117
Adrian Seungjin Lee Avatar answered Sep 22 '22 14:09

Adrian Seungjin Lee


I try to do something similar and found this solution :

render() {
    var _data = texts;
    return (
        <View style={styles.container}>
        { _data.map(function(object,i) {
            return (
                <Text ref={i}
                  onPress={() => this.rowPressed(i)}
                  style={styles.raceText}>{texts[i].text}
                </Text> );
            })
        }
        </View>
    );
}

Cheers

like image 24
cdcl Avatar answered Sep 22 '22 14:09

cdcl