CLOSE
_onPress(e) {
In react native v.0.42 you need this statement:
import ReactNativeComponentTree from 'react-native/Libraries/Renderer/src/renderers/native/ReactNativeComponentTree';
ReactNativeComponentTree.getInstanceFromNode(e.target)._currentElement;
Another way to solve the problem in question is by using a ref (together with createRef) like so:
const touchableRef = React.createRef();
return (
<TouchableWithoutFeedback
ref={touchableRef}
onPress={() => /* use touchableRef.current */ undefined}
/>
);
Another advantage of doing that is that the ref can be really anything, doesn't have to be the touched node.
This is how I ended up resolving similar situation for myself. It doesn't follow the same approach by any means but did it the trick!
onItemPressed(item) {
this.props.navigateForward(item.sceneId);
this.props.closeDrawer();
}
render() {
var listItems = [];
for (var i=0; i < this.props.navigation.scenes.length; i++) {
var item = this.props.navigation.scenes[i];
listItems.push(<ListItem
onPress={this.onItemPressed.bind(this, item)}
key={i}
title={item.title}
leftIcon={{name: item.icon}}
underlayColor={colors.lightPrimary}
containerStyle={styles.menuItemStyle}
titleStyle={styles.menuItemTitle}
/>);
}
return (
<View style={styles.container}>
<List containerStyle={styles.listContainer}>
{listItems}
</List>
</View>
)
};
The concern is about performance so I solve it with this approach
just create a wrapper around TouchableOpacity or any clickable view
import { TouchableOpacity } from "react-native"
export const TouchableOpacityOnPressOptimized = ({ children, onPress, index }) => {
return (
<TouchableOpacity onPress={() => onPress(index)}>
{children}
</TouchableOpacity>
)
}
const touchMe = (index) => {
switch(index) {
case 1: alert('index is' + index)
case 2: alert('index is' + index)
}
}
<TouchableOpacityOnPressOptimized index={1} onPress={touchMe}> touch me 1 </TouchableOpacityOnPressOptimized>
<TouchableOpacityOnPressOptimized index={2} onPress={touchMe}> touch me 2 </TouchableOpacityOnPressOptimized>
<TouchableOpacityOnPressOptimized index={3} onPress={touchMe}> touch me 3 </TouchableOpacityOnPressOptimized>
this way your touchable component not re-render
The code to do it changed recently when React / React Native common code was moved around, but what I would suggest is to check out Inspector code and available methods on the ReactNativeComponentTree
More specifically, the following code should do the trick for you:
var ReactNativeComponentTree = require('react/lib/ReactNativeComponentTree');
ReactNativeComponentTree.getInstanceFromNode(nativeTag);
In case somebody stumbles on that question, ReactNativeComponentTree
was removed from version 0.56 or so.
However, I found a much cleaner way to detect a tap on a certain (sub-)element:
import React from 'React';
import {
Text,
TouchableOpacity,
View,
findNodeHandle
} from 'react-native';
class TestClass extends React.Component {
onTap = (evt) => {
// Retrieve the handle of the second <Text> node
let elementHandle = findNodeHandle(this.refs["element"]);
// Check if the tapped element's node-id equals the retrieved one
if (evt.nativeEvent.target == elementHandle) {
// Do something when element was clicked
console.log("Second <Text> node was tapped")
}
}
render() {
return (
<TouchableOpacity onPress={this.onTap}>
<View>
<Text>Hi there!</Text>
<Text ref="element">Only detect this element</Text>
</View>
</TouchableOpacity>
);
}
};
Basically, we are just using a reference (ref
) to access the node-id of an element using findNodeHandle
.
We then compare that node-id with the nativeEvent.target
node-id in order to check if a sub-element was tapped.
In the above example, only the second <Text>
node produces an output.