Here is my render function of react native. if i put listview it works. if i put touchablehighlight it works. but, if it put both it doesn't work. need help.
render: function() {
return (
/* ListView wraps ScrollView and so takes on its properties.
With that in mind you can use the ScrollView's contentContainerStyle prop to style the items.*/
<ListView
contentContainerStyle={styles.list}
dataSource={this.state.dataSource}
renderRow={this._renderRow}/>
<TouchableHighlight onPress={() => this._pressRow(rowID)} underlayColor="transparent">
</TouchableHighlight>
);
},
what is wrong here? need both components to work.
You can't have 2 tags that you can return. You should wrap it inside a <View> </View> tag. This way you can abstract multiple components that you need in the page.
render: function() {
return (
/* ListView wraps ScrollView and so takes on its properties.
With that in mind you can use the ScrollView's contentContainerStyle prop to style the items.*/
<View>
<ListView
contentContainerStyle={styles.list}
dataSource={this.state.dataSource}
renderRow={this._renderRow}/>
<TouchableHighlight onPress={() => this._pressRow(rowID)} underlayColor="transparent">
</TouchableHighlight>
</View>
);
},
Hope it helps.
Related
I am working with react native and expo.cli and would like to know how I can manage to add a handle to a TouchableOpacity, I have the following component:
function MainModal (){
return(
<>
<View style={{flexDirection: 'row'}}>
<TouchableOpacity
onPress={this.TouchableOpacity}
>
<Text>Volver</Text>
</TouchableOpacity>
</View>
</>
What I want to do is make a reference to this specific TouchableOpacity when it is selected, but when I use a "this" nested in the component I get the following error: Undefined is not an object (Evaluating 'this.TouchableOpacity') I know maybe This question is a bit of a novice and has more to do with how 'this' works in javascript than with React Native itself, however I can't find a way to make a reference to the selected object so that it executes something when selected. How could I do it?
You can use React.useRef() hook to create a reference to that element so you can access then to it. The idea you have of this is not the actual this. This might refer to the global object (in not strict) and might be undefined in strict mode. If you want to use this in a component I recommend you to create a class component instead of a function one. See this in MDN to learn more of it.
Anyway, the use of ref in a functional component would be this:
function MainModal (){
const touchableReference = React.useRef()
const handleTouchableClick = () => {
console.log(touchableReference.current)
//
// Outputs HTMLDivElement...
//
}
return(
<>
<View style={{flexDirection: 'row'}}>
<TouchableOpacity
ref={touchableReference}
onPress={() => handleTouchableClick()}
>
<Text>Volver</Text>
</TouchableOpacity>
</View>
</>
)
}
One standard way of passing event handler in functional component is as follows
function MainModal (props){
const onPress1 = useCallback(()=>console.log); // created inside the componet
const {onPress2} = props; // passed from props
const {onPress3} = useSomeHook(); // from context/hook
return(
<>
<View style={{flexDirection: 'row'}}>
<TouchableOpacity
onPress={onPress1}
>
<Text>Volver</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={onPress2}
>
<Text>Volver</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={onPress3}
>
<Text>Volver</Text>
</TouchableOpacity>
</View>
</>
);
}
The behaviour of this works the same in react and react-native. React functional component is executed during the render phase and you are not suppose to work with this here, given that you do not understand when and where it is called.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
i got an problem with the refreshing on pull function. The FlatList renders fine, but pull to refresh is not working. This is my current sourcecode:
return (
<View style={GlobalStyles.flex1}>
<FlatList
showsVerticalScrollIndicator={false}
refreshControl={
<RefreshControl
refreshing={isRefreshing}
onRefresh={() => {
console.log("onRefresh loadVocable");
loadVocables();
}}
/>
}
data={vocables}
keyExtractor={vocable => vocable.id}
onEndReached={() => {
if (!isRefreshing && !endReached) {
loadVocables();
}
}}
renderItem={vocable => (
<TouchableOpacity
onPress={() => {
props.navigation.navigate({ routeName: "editVocable", params: { vocable: vocable.item } });
}}
onLongPress={() => {
handleLongPress(vocable.item.id);
}}>
<Card style={styles.cardStyle}>
<View style={styles.part1}>
<Text style={styles.vocableText}>{vocable.item.wordENG}</Text>
<Text style={styles.vocableText}>{vocable.item.wordDE}</Text>
</View>
<View style={styles.part2}>
<Ionicons name={vocable.item.known ? "md-checkmark-circle" : "md-close-circle"} size={23} color={vocable.item.known ? Colors.success : Colors.danger} />
</View>
</Card>
</TouchableOpacity>
)}
/>
</View>
);
In the official docs is an example that says contentContainerStyle needs to be flex: 1 to know the height, that makes sence to me, so when i set contentContainerStyle with flex 1, refresh on pull works fine, but then i can't scroll anymore in the Flatlist and everthing get very tight, so the style also change then. Does anyone know why this happen?
The first picture is with "contentContainerStyle={{flex: 1}}" and the last one is without contentContainerStyle.
The answer was so easy, I compared a new project (there worked my code) to the one where the problem was and after 5 days I found the little error:
My import was wrong!
I imported FlatList like this:
import { FlatList } from "react-native-gesture-handler";
But it needs to get imported from React-Native so like this:
import { FlatList } from "react-native";
Thanks to #The1993, without the hint to compare the projects, maybe I would stuck forever on this error :D In the future I will compare working files to find any error!
contentContainerStyle is used to style inner content e.g items alignments, padding, etc
style is used to align its height and relations
You can replace style={{flex: 1}} instead of contentContainerStyle or wrap the parent element with flex: 1
Hello there i am working on a beginner project of mine with React Native and right now i am not able to handle onPress event.
Render:
_renderRow(feed) {
return (
<TouchableHighlight onPress={() => this._pressRow()}>
<View style={styles.container}>
<Image
source={{uri: feed.thumbnail}}
style={styles.thumbnail}/>
<View style={styles.rightContainer}>
<Text style={styles.title}>{feed.title}</Text>
</View>
</View>
</TouchableHighlight>
);
}
And the onPress function
_pressRow() {
console.log('list item pressed')
}
Listview
<ListView
dataSource={this.state.dataSource}
renderRow={this._renderRow}
style={styles.listView}/>
This is what i get as an error.
undefined is not a function (evaluating _this3._pressRow())
EDIT
Thanks to #Cherniv. I forgot to bind this with the renderRow function, changed my code like that and worked as intended:
<ListView
dataSource={this.state.dataSource}
renderRow={this._renderRow.bind(this)}
style={styles.listView}/>
Is it not because you forgot the "_" before pressRow in method declaration ?
So Basically I am getting error in the title which is related to the navigator.
The error pops up when I press on the Icon.
What I basically want to do is make a Tab bar at the top that switches between three different views: feed, wiki, and message board
Here is my index.android.js: (imports Nav)
_renderScene(route, navigator) {
var globalNavigatorProps = {navigator};
switch(route.ident) {
case "FeedView":
return(
<Feed
{...globalNavigatorProps}
/>
);
case "WikiView":
return(
<View>
<Text>
{'Hello'};
</Text>
</View>
);
case "BoardView":
return(
<View>
<Text>
{'Hello'};
</Text>
</View>
);
default:
console.log(`Something went wrong ${route}`);
}
}
render(){
return(
<View>
<Nav />
<Navigator
initialRoute={{ident:"Feed"}}
ref="appNavigator"
renderScene={ this._renderScene }
/>
</View>
);
}
Here is my Nav.js:
constructor(props){
super(props);
}
render(){
console.log(this.props.navigator);
return(
<View style={{flexDirection: "column"}}>
<View style={styles.nav}>
<Icon onPress={(event) => this.props.navigator.push({ident: "Feed"})} name="newspaper-o" size={22}/>
<Icon name="wikipedia-w" size={22}/>
<Icon name="comments" size={22}/>
</View>
<View style={styles.divider}/>
</View>
);
}
_changeView(type){
}
I dont think this is the issue, but the renderScene function won't be bound to the react component.
Try turning renderScene={ this._renderScene } into renderScene={ this._renderScene.bind(this) }
If you are trying to implement a tabbed view there are better ways of doing it you can always use an open source module such as this one https://github.com/skv-headless/react-native-scrollable-tab-view
the developer has made it in such a way that it is easy to use and the example is good enough to get through most of the part.
So instead of creating such components yourself what I would suggest is to use the modules made by the community.
Hope my answer was helpful.
this error always occurs when you didnt bind(this),check you Icon module onPress method
In my scenario there are two Views.
While load the component i need to none second view after while click
on TextInput need to open the second view after selecting the value
from the second view selected value should be populate in the first
view TextInput after that secondView should be closed.I can acheieve
the same effect using react.js but the same effect i am unable to do
using react native .
var ViewDisplay = React.createClass({
componentDidMount(){
this.refs.secondView.getDOMNode().style.display="none";
},
clickHandler:function(){
this.refs.secondView.getDOMNode().style.display="block";
},
populateValue:function(){
this.refs.secondView.getDOMNode().style.display="none";
},
render:function(){
return(<View>
<View ref={firstView}>
<TextInput style={styles.textInput} placeholder= {enter value} onEndEditing={this.clickHandler}/>
</View>
<View ref={secondView}>
<TouchableHighlight underlayColor="#ffa456" onPress={this.populateValue}>
<Text ref={key}>first</Text>
</TouchableHighlight>
<TouchableHighlight underlayColor="#ffa456" onPress={this.populatevalue}>
<Text>Second</Text>
</TouchableHighlight>
<TouchableHighlight underlayColor="#ffa456" onPress={this.populatevalue}>
<Text>third</Text>
</TouchableHighlight>
</View>
</View>)
}
})
Try setting a flag in your component state with the click handler, then use that to determine which view should be rendered
render() !this.state.clicked ? <View ref={firstView}> ... </View> : <View ref={secondView}> ... </View>