onPress of TouchableOpacity gets called when loading Flatlist - reactjs

I have a flatlist with a search function. In the next step, I want something to happen when I press within the item. I'm facing the problem that the TouchableOpacity is visible, but nothing happens when it's pressed. I've tried the same with a Button and face the same issue.
Instead of onPress being called when something is pressed, it somehow get's called once the screen loads immediately. If I for example console.log(item.title) I get all the titles in my console log that are currently in the flatlist.
I've tried to figure out what is causing this for many hours, but can't seem to find any reason. Any help is highly appreciated.
I have a Flatlist that is populated with data, set up as follows:
return (
<View style={styles.list}>
<FlatList
data = {this.state.data}
renderItem={renderListItem}
keyExtractor={item => item.id}
ListHeaderComponent={this.renderHeader}
/>
</View>
);
}
}
const renderListItem = (item) => {
return (
<MyTouchable
id={item.item.id}
title={item.item.title}
/>
);
}
MyTouchable Component looks like this:
<View>
<TouchableOpacity onPress={console.log("Pressed")}>
<View style={styles.mainView}>
<View>
<Text style={styles.text}>{props.id} {props.title}</Text>
</View>
</View>
</TouchableOpacity>
</View>

Try to pass the console.log inside an arrow function
<TouchableOpacity onPress={() => console.log("Pressed")}>
...
</TouchableOpacity>

You can’t write like this: <Component makeThing={myFunc()} />. You should write like that: <Component makeThing={() => myFunc()} /> if you are not using useCallback.
Make sure to read the docs about passing functions to components.
You must provide and arrow function, and call your function inside it.
Or just use useCallback hook:
const Component = () => {
const myFunction = useCallback(() => {
// do something
}, []);
return <AnotherComponent coolFunction={myFunction} />
}

Related

How to Limit render element Flat List and add more content in React Native

I want like that flatlist render only 5 checkbox items and then when I click to +5 more button it will show 5 more checkbox list.In this all checkbox list appearing but i want only five
Please help me how to achieve that
Thanks in advance
const renderResourceList = renderData => {
return (
<FlatList
data={renderData}
initialNumToRender={5}
maxToRenderPerBatch={5}
pagingEnabled={true}
nestedScrollEnabled={true}
renderItem={({item}) => (
<View style={styles.card}>
<TouchableOpacity
onPress={() => {
if(resourceTypeArray.includes(item)){
setResourceTypeArray(currentList => {
return currentList.filter(items => items !== item);
});
}
else{
setResourceTypeArray(currentList => [
...currentList,
item
]);
}
onSetResourceType(item);
}}
style={styles.modalBtn}>
<Icon
name={
resourceTypeArray.includes(item) ? 'checkbox-marked' : 'checkbox-blank-outline'
}
size={18}
color="#353C3C"
style={{bottom: -1}}
/>
<View style={styles.textWrapper}>
<Text style={styles.modalText}>{item.charAt(0)}
{item.toLowerCase().slice(1).replace(/_/g, ' ')}</Text>
</View>
</TouchableOpacity>
</View>
)}
/>
);
};
I tried but this not working
I used a package called flatlist-react to handle this for me. A decent tutorial for this can be found here.
With this package, you can directly specify and limit the items rendered with the limit prop. Here is an example:
<FlatList
limit="2,-2"
list={people}
renderItem={Person}
/>
If you keep track of the limit prop variables using state, you can dynamically change these values when you click 5+ more in order to render whatever part of your data you would like.

Issue on Hide/Show component in React Native

I am new in React native development and i am trying to do something simple. I have 4 components <TouchableOpacity> in a React Class extending Component.
In the render function, i am trying to hide three of these components while i am pressing on one.
render(){
[...]
return (
<TouchableOpacity style={styles.filterButtonAll} onPress={()=>this.toggleStatus()}>
<Ionicons size={15} name='XXX'> Show/Hide</Ionicons>
</TouchableOpacity>
<TouchableOpacity style={styles.filterButton}>
<Ionicons size={15} name='XXX'> Text1</Ionicons>
</TouchableOpacity>
<TouchableOpacity style={styles.filterButton}>
<Ionicons size={15} name='XXX'> Text2</Ionicons>
</TouchableOpacity>
<TouchableOpacity style={styles.filterButton}>
<Ionicons size={15} name='XXX'> Text3</Ionicons>
</TouchableOpacity>
[...]
)
}
toggleStatus function :
toggleStatus(){
this.state.showMenu = !this.state.showMenu;
};
And i have my showMenu in my state.
I tried conditional, and many other things following many posts about this subject, but when i am logging {this.state.showMenu} , it is dynamic in my toggleStatus() function but it's always the same value in my render function.
I think i am doing something wrong, thanks in advance for your help :)
The way your updating your state is incorrect. You have to call a function called setState() and then pass the updated state.
Reference for setState: https://reactjs.org/docs/react-component.html#setstate.
Example:
toggleStatus(){
this.setState({showMenu : !this.state.showMenu}); // RIGHT
// this.state.showMenu = !this.state.showMenu; // WRONG
};
Recommend way:
basically when your state update depend upon the previous state its better to use this approach.
toggleStatus(){
this.setState((state, props) => {
return {showMenu: !state.showMenu};
});
// this.state.showMenu = !this.state.showMenu; // WRONG
};

FlatList rendering is heavy for big data set

In my application I have a FlatList with dataset of 100 items in it. Each item has a complex UI and I noticed that it's taking a heavy toll on performance. The page that has the list takes up to 5 seconds to load.
I noticed that the moment the component is rendered for the first time, the renderItem function of the FlatList is also called for each and every item in my data set, I also noticed that it also happens if there any other setState change for other stuff on that page. Is there a way to prevent this re-rendering of the flat list or at least to re-render only the visible items - just like with Recycle with in native Android?
How can I only render the visible items when the component first appears?
I tried to use initialNumToRender and maxToRenderPerBatch but neither have worked.
Here is an example of the code:
const Item = ({ title }) => (
<View style={styles.item}>
<Text style={styles.title}>{title}</Text>
</View>
);
const App = () => {
const [text, setText] = React.useState('')
const renderItem = ({ item }) => {
console.log("Render Item")
return (<Item title={item.title} />)
};
return (
<SafeAreaView style={styles.container}>
<TextInput
value={text}
onChangeText={(val) => setText(val)}
/>
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={item => item.id}
initialNumToRender={6}
maxToRenderPerBatch={6}
/>
</SafeAreaView>
);
}
If I try to type something in TextInput the whole list re-renders but nothing in the list has changed.. how can I prevent this?

Big Space between items in FlatList

I'm implementing Comment Page like Facebook. Somehow I'm getting a plenty of white space. Check this out!
When I scroll it to the bottom... the rest of comments are there.. so weird
Here is my render function and FlatList
render() {
return (
<RkAvoidKeyboard style={styles.bigContainer} onResponderRelease={(event) => {
Keyboard.dismiss();
}}>
<FlatList
ref='list'
style={styles.root}
data={this.props.comments}
ItemSeparatorComponent={this._renderSeparator}
keyExtractor={this._keyExtractor}
renderItem={this._renderItem}/>
{this._renderKeyboard()}
</RkAvoidKeyboard>
)
}
_keyExtractor(item, index) {
return item.id;
}
_renderSeparator() {
return (
<View style={styles.separator}/>
)
}
I set the background color of the FlatList and it colors all screen (except the keyboard and navigation). I didn't notice this until I implement my Keyboard input. So nothing wrong with Keyboard.
This is so werid..!!
To me the space looks exactly the size of keyboard, instead of using the RkAvoidKeyboard spacer, try using react-native-keyboard-spacer
Its easy to set up and you will just have to set it under your comment textInput component or at the bottom of the container whichever suits you.
Here is a sample that I can provide and that may help you
<View>
<FlatList
data = {dataSource}
renderItem = {({item}) => this._renderFlatListItem(item)}
keyExtractor = {(item) => item.id}
/>
<View style={style.textInputContainer}>
<TextInput
placeholder={"Text goes here"}
ref={input => { this.textInput = input }}
onChangeText={(text) => this.setState({currentMessage:text})}
value={this.state.message}
multiline={true}
underlineColorAndroid = {'transparent'}
/>
<TouchableHighlight
underlayColor={'transparent'}
style={style.sendButtonContainer}
onPress = {() => {this._sendMessage();}}>
<Image source={require('../../Assets/Images/shape.png')}
style={style.sendButton} resizeMode="contain"/>
</TouchableHighlight>
</View>
<KeyboardSpacer/>
All the best!
I was getting null for my Avatar Image and that showed huge blank list.
I figured this out while printing all comments on console.
Thank you guys!

React Native Component not re-rendering despite render function running

I am a little baffled here ..
I have some code like this
renderTopic(topic){
if(topic.isMine){console.log('work?')}
return (
<View key={topic.id.toString()} >
<TouchableOpacity onPress={() => this.addToic.call(this, topic)} >
{topic.isMine && <Topic topic={topic} active={true}/>}
{!topic.isMine && <Topic topic={topic} active={false}/>}
</TouchableOpacity>
</View>
)
}
render() {
console.log("re-rendering", this.props.myTopics)
return (
<View style={s.welcome}>
<ScrollView>
<View style={s.topics}>
{this.props.me.myTopics.map(topic => this.renderTopic(topic) )}
</View>
</ScrollView>
</View>
)
}
The problem is when I update topics using the traditional redux -> 'dispatch action' method, the re-render function fires, the should component update function fires, everything looks like it works but the topic.isMine conditional rendering never updates and switches the components over.
The correct result is displayed if I change page, the app then re-renders correctly.
Probably your reducer does not create new topic object. React sees, that reference to new topic matches old topic and skips calling renderTopic(topic) with same reference value as before.

Resources