React Native how to add button inside Flatlist? - javascript

How can I add a button inside flatlist, whenever I tried to add a button then I am getting multiple buttons inside flatlist.
I want only one button which is scrollable with flatlist.
and if I add a button outside flatlist then it's not scrolling, it get fixed below the flatlist, only flatlist data scroll but the button not scroll with flatlist. How can I solve this issue? Really appreciate your support.
import React, { useState, useEffect } from 'react';
import {View, Button, Text, FlatList, StyleSheet, Pressable, TouchableOpacity} from 'react-native'
import {firebase} from '../config';
const Testing = ({ navigation }) =>{
const [users, setUsers] = useState([]);
const todoRef = firebase.firestore().collection('testing');
useEffect(() => {
todoRef.onSnapshot(
querySnapshot => {
const users = []
querySnapshot.forEach((doc) => {
const { one, two, three, four, five
} = doc.data()
users.push({
id: doc.id,
one, two, three, four, five
})
})
setUsers(users)
}
)
}, [])
return (
<View style={{ flex:1,}}>
<FlatList
style={{height: '100%'}}
data={users}
numColumns={1}
renderItem={({item}) => (
<Pressable>
<View>
<View>
<Text style={[styles.card, styles.surah]}>{item.one}</Text>
<Text style={styles.card}>{item.two}</Text>
<Text style={styles.text}>{item.three}</Text>
<Text style={styles.cardTwo}>{item.four}</Text>
<Text style={styles.text}>{item.five}</Text>
</View>
</View>
// I tried to add here button but it's not worked
</Pressable>
)}/>
// I also tried to add here button but it's not worked
</View>
);}
export default Testing;

You could implement this with the help of the index parameter of the renderItem function.
renderItem={({item, index}) => (
<View>
<View>
<Text style={[styles.card, styles.surah]}>{item.one}</Text>
<Text style={styles.card}>{item.two}</Text>
<Text style={styles.text}>{item.three}</Text>
<Text style={styles.cardTwo}>{item.four}</Text>
<Text style={styles.text}>{item.five}</Text>
</View>
{
index === users.length - 1 && <Pressable onPress={...}>...</Pressable>
}
</View>
)}
The above adds a component, in this case a Pressable at the end of the last item. If you want the last item to be pressable, then you can achieve this using the same pattern, but by wrapping the last component inside a pressable.
const InnerComponent = () => {
return <View>
<Text style={[styles.card, styles.surah]}>{item.one}</Text>
<Text style={styles.card}>{item.two}</Text>
<Text style={styles.text}>{item.three}</Text>
<Text style={styles.cardTwo}>{item.four}</Text>
<Text style={styles.text}>{item.five}</Text>
</View>
}
...
renderItem={({item, index}) => (
<View>
{
index === users.length - 1 ? <Pressable onPress={...}>
<InnerComponent />
</Pressable> : <InnerComponent />
}
</View>
)}

Related

react native flatlist doesn't show updated value

I'm having a trouble in a flatlist that a button increments the value but doesn't show if I don't refresh or hit ctrl-s after incrementing value. Basically I cannot see the value change without pressing ctrl-s or going to another page and returning to the same page.
<FlatList
data={store}
renderItem={({ item }) => {
return (
<View style={styles.itemCountView}>
<TouchableOpacity style={styles.up}
onPress={() => item.itemCount++}>
<MaterialIcons name="arrow-drop-up" size={36} color="#ddd"/>
</TouchableOpacity>
<Text style={styles.itemCountText}>{item.itemCount}</Text>
</View>
)
}}
/>
I can increment the value, if I save or go to another page and come back the value changes and i can see it but there must be a way to see it change.
Any help is appreciated
As per the Documentation
extraData: https://reactnative.dev/docs/flatlist#extradata
A marker property for telling the list to re-render (since it implements PureComponent). If any of your renderItem, Header, Footer, etc. functions depend on anything outside of the data prop, stick it here and treat it immutably.
I think you'r not saving the changes you doing, basically you need to update the the store variable each time you increment an item, something like:
<FlatList
data={store}
renderItem={({ item }) => {
return (
<View style={styles.itemCountView}>
<TouchableOpacity style={styles.up}
onPress={() => {
const newStoreData = [...store]
const itemIndex = newStoreData.findIndex(item)
const newItem = {...item,itemCount:item.itemCount ++}
newStoreData[itemIndex] = newItem
setStoreData(newStoreData) // state or redux?
}
}>
<MaterialIcons name="arrow-drop-up" size={36} color="#ddd"/>
</TouchableOpacity>
<Text style={styles.itemCountText}>{item.itemCount}</Text>
</View>
)
}}
/>
You can try this approach here:
import {useState} from 'react';
import { Text, View, FlatList, TouchableOpacity } from 'react-native';
const store = [{
itemCount: 1
},
{
itemCount: 2
},
{
itemCount: 3
}]
export default function App() {
return (
<View style={{
flex: 1,
padding: 140,
}}>
<FlatList
data={store}
renderItem={({ item }) => ( <Item item={item}/> )}
/>
</View>
);
}
const Item = ({item})=> {
const[count, setCount] = useState(item.itemCount);
return (
<View>
<TouchableOpacity
style={{
backgroundColor: 'black',
padding: 10,
margin: 10
}}
onPress={() => setCount(count+1)}>
<Text style={{
color: 'white'
}}>{count}</Text>
</TouchableOpacity>
</View>
)
}
This will set the state for each item in the Flatlist.

How to set searchbar in react native

I am a new in react native i am try to set search bar in my application. To search in flatlist data. i am not able to search in flatlist data ,What is the error i don't know. how can i set how to resolve my problem please resolve my issue. i have attached the my code given below.
import React from 'react';
import { StyleSheet, FlatList, View, TouchableOpacity, Image, Text, TextInput } from 'react-native';
import { dishesData } from './DishesData';
import { SearchBar } from 'react-native-elements'
const MenuListScreen = ({ navigation }) => {
const state = {
searchText: "",
dishesData:[],
filteredData: [],
};
let search = (searchText) => {
this.setState({searchText: searchText});
let filteredData = state.dishesData.filter(function (item) {
return item.description.includes(searchText);
});
this.setState({filteredData: filteredData});
};
return (
<View style={styles.container}>
<SearchBar
round={true}
lightTheme={true}
placeholder="Search..."
autoCapitalize='none'
autoCorrect={false}
onChangeText={search}
value={state.searchText}
/>
<FlatList style={styles.list}
contentContainerStyle={styles.listContainer}
data={dishesData}
horizontal={false}
numColumns={1}
keyExtractor={(item) => {
return item.id;
}}
renderItem={({ item }) => {
return (
<TouchableOpacity
onPress={() => navigation.navigate('MenuDetail', { id: item.id })}
>
<Image
style={styles.userImage}
source={{ uri: item.imageSource }}
/>
<View style={styles.cardFooter}>
<View style={{ alignItems: "center", justifyContent: "center" }}>
<Text style={styles.name}>{item.title}</Text>
<Text style={styles.position}>{item.price}</Text>
{/* <TouchableOpacity style={styles.followButton}
onPress={() =>
props.navigation.navigate('DetailsPage', item)
}>
<Text style={styles.followButtonText}>Buy Now</Text>
</TouchableOpacity> */}
</View>
</View>
</TouchableOpacity>
)
}} />
</View>
);
};
Hi there you can filter items by using filter function and you are already doing that but for accuracy I'll suggest to do like this.
let search = (searchText) => {
this.setState({searchText: searchText});
let filteredData = state.dishesData.filter(function (item) {
return item.description.toUpperCase().includes(searchText.toUpperCase());
});
this.setState({filteredData: filteredData});
};
and to render the filtered items on Flatlist you have to toggle data array on FlatList
<FlatList style={styles.list}
contentContainerStyle={styles.listContainer}
data={state.searchText ? state.filteredData:state.dishesData}
horizontal={false}
numColumns={1}
keyExtractor={(item) => {
return item.id;
}}.../>
Here is the Snack Link you can test as well Working Example

How to show an item from an array in json to a react native modal unique on button click

I have an array of data stored in a JSON file. It has ID, title and description. Now I have listed out the titles in my ReactNative app. I want to display the content of each title on a modal. How can I do that?
Below is my code where the modal will come up, but the description won't appear on the modal. Instead it gives an error that it's not defined.
import { StatusBar } from "expo-status-bar";
import React, { useState } from "react";
import {
Modal,
Platform,
SafeAreaView,
ScrollView,
StyleSheet,
Text,
View,
} from "react-native";
export default function App() {
const data = require("./dummyData.json");
let modalData = [];
const [showStanzas, SetshowStanzas] = useState(false);
const onpressHandler = function (a, b) {
modalData = data[b];
SetshowStanzas(true);
};
return (
<SafeAreaView style={styles.container}>
<View style={styles.headingView}>
<Text style={styles.heading}></Text>
</View>
<ScrollView>
<View style={styles.container2}>
<View style={styles.container3}>
{data.map((datas, id) => {
return (
<View key={id}>
<Text
style={styles.hymnTitle}
onPress={() => {
onpressHandler(true, id);
}}
>
{datas.id}. {""}
{datas.title}{" "}
</Text>
</View>
);
})}
<Modal
animationType={"slide"}
visible={showStanzas}
onRequestClose={() => SetshowStanzas(false)}
>
<View>
<Text style={styles.desc}> {modalData.description} </Text>
</View>
</Modal>
</View>
</View>
</ScrollView>
</SafeAreaView>
);
}
Migrate the local variable modalData to a React state
const [mobileData, setMobileData] = useState();
Then store the selected index data on the on onpressHandler
const onpressHandler = function (a, b) {
setMobileData(data[b]);
SetshowStanzas(true);
};
Your modal code should work afterwards

React-native autocomplete issue ("Objects are not valid as a Reach child")

I'm trying to use Autocomplete in React-native but I'm obviously doing something wrong.
Here a minimal example of code showing what I'm doing:
import React, {useState, useEffect} from 'react';
import {
SafeAreaView,
StyleSheet,
TextInput,
Text,
TouchableOpacity,
View,
} from 'react-native';
import Autocomplete from 'react-native-autocomplete-input';
const DATA =
[{"id": 1,"title": "test1"},{"id": 2,"title": "test2"},{"id": 3,"title": "test3"}]
const App = () => {
const [query, setQuery] = useState('');
return (
<SafeAreaView style={{flex: 1}}>
<View style={styles.container}>
<Autocomplete
autoCapitalize="none"
autoCorrect={false}
data={DATA}
value={query}
onChangeText={setQuery}
renderItem={({item}) => (
<TouchableOpacity
onPress={() => {}}>
<Text>
{item.title}
</Text>
</TouchableOpacity>
)}
/>
</View>
</SafeAreaView>
);
};
I reduced the code to the very minimum.
However, I keep getting error:
"Objecs are not valid as a React child (found: object with keys {id,title}"
It seems I'm missing something very obvious about renderItem (I guess), but since I'm stuck since a few hours, another eye could spot what I'm doing wrong.. any help would be appreciated, thanks.
Your destructuring was wrong. do like below {id,title}. renderItem is array of iteration so its look like object.
renderItem={({title,id}) => (
<TouchableOpacity
onPress={() => {}}>
<Text>
{title}
</Text>
</TouchableOpacity>
)}
I actually found the answer.
It seems, I haven't read correctly the list of props for Autocomplete: in fact, renderItem must be passed inside an option called "flatListProps".
Correct code is below:
import React, {useState, useEffect} from 'react';
import {
SafeAreaView,
StyleSheet,
TextInput,
Text,
TouchableOpacity,
View,
} from 'react-native';
import Autocomplete from 'react-native-autocomplete-input';
const DATA =
[{"id": 1,"title": "test1"},{"id": 2,"title": "test2"},{"id": 3,"title": "test3"}]
const App = () => {
const [query, setQuery] = useState('');
return (
<SafeAreaView style={{flex: 1}}>
<View style={styles.container}>
<Autocomplete
autoCapitalize="none"
autoCorrect={false}
data={DATA}
value={query}
onChangeText={setQuery}
flatListProps={{
keyboardShouldPersistTaps: 'always',
keyExtractor: (item) => item.id,
renderItem: ( ({item}) => (
<TouchableOpacity
onPress={() => {}}>
<Text>
{item.title}
</Text>
</TouchableOpacity>
))
}}
/>
</View>
</SafeAreaView>
);
};
renderItem={({ item, i }) => (
<TouchableOpacity key={i} onPress={() => ()}>
<Text>{item.label}</Text>
</TouchableOpacity>
)}
You have to pass the index to key.

How to pass and execute functions as props in class Component in React Native?

I'm a beginner in React Native and struggling in passing and executing functions as props from parent to child component. Here's the code:
MainMap
import React from 'react';
import {
TouchableWithoutFeedback,
StyleSheet,
View,
Button,
FlatList,
Dimensions
} from 'react-native';
import PlaceInput from '../components/PlaceInput';
const INCREMENT = 1;
const HEIGHT = Dimensions.get('window').height
const WIDTH = Dimensions.get('window').width
class MainMap extends React.Component{
constructor(props){
super(props);
this.state={
numOfInput:[],
counter: 0,
}
this.onAddSearch = this.onAddSearch.bind(this)
this.onDeleteSearch = this.onDeleteSearch.bind(this)
}
onAddSearch(){
this.setState((state) => ({
counter: state.counter + INCREMENT,
numOfInput: [...state.numOfInput, state.counter]
}))
}
onDeleteSearch(inputId){
const items = this.state.numOfInput.filter(item => item.id !== inputId)
this.setState({
numOfInput: items
})
}
render(){
return(
<TouchableWithoutFeedback onPress={this.hideKeyboard} >
<View style={styles.container} >
<Button title='Add a location' onPress={this.onAddSearch} />
<View style={{height: HEIGHT/2 }}>
<FlatList
data={this.state.numOfInput}
keyExtractor={(item, index) => item.id}
renderItem={itemData => {
return(
<PlaceInput
key={itemData.item.id}
// id={itemData.item.id}
onDelete={this.onDeleteSearch}
showDirectionOnMap={this.showDirectionOnMap}
userLatitude={userLatitude}
userLongitude={userLongitude}
/>
)
}}
/>
</View>
</View>
</TouchableWithoutFeedback>
)
}
}
export default MainMap;
const styles = StyleSheet.create({
container:{
flex: 1
},
})
Here's the PlaceInput component
class PlaceInput extends React.Component{
constructor(props){
super(props);
... // These lines have no relation to what I'm asking so don't mind them
}
...
render(){
return(
<View style={styles.buttonContainer} >
<View style={{flex: 1, alignItems: 'center'}}>
<Text style={{fontSize: 8}}>{'\u25A0'}</Text>
</View>
<View style={{flex: 4}}>
<TextInput
autoCorrect={false}
autoCapitalize='none'
style={styles.inputStyle}
placeholder='Search your places'
onChangeText={(input) => {
this.setState({destinationInput: input});
this.getPlacesDebounced(input);
}}
value={this.state.destinationInput}
/>
{/* {predictions} */}
</View>
<View style={styles.rightCol}>
<TouchableOpacity onPress={this.props.onDelete.bind(this, this.props.id)}>
<Ionicons name='md-car' size={25} style={{alignSelf: 'center'}} />
</TouchableOpacity>
</View>
</View>
)
}
}
What I'm trying to do:
Define a function to execute in MainMap.js (in FlatList --> PlaceInput for specific) , which is to delete an search bar( the whole PlaceInput in the FlatList) every time I click the right symbol of that search bar. The function is onDeleteSearch
The right symbol is styled in a TouachableOpacity as you can see in the PlaceInput.js component. I put it in the last View pair
However, When I click, the screen deletes all the search bars, not the one I click. Is it the problem of the id of the component PlaceInput ? Or with the way I call the props?...
Please help me !
<TouchableOpacity onPress={this.props.onDelete.bind(this, this.props.id)}>
<Ionicons name='md-car' size={25} style={{alignSelf: 'center'}} />
</TouchableOpacity>
Don't bind, just call this.props.onDelete(this.props.id);
In MainMap, try this:
<PlaceInput
key={itemData.item.id}
// id={itemData.item.id}
onDelete={() => this.onDeleteSearch(itemData.item.id)} // here
showDirectionOnMap={this.showDirectionOnMap}
userLatitude={userLatitude}
userLongitude={userLongitude}
/>
Assuming the function:
onPressed(optionalArgument = false) {
// do something
}
You can pass a function to onPress if it does not require any arguments, i.e
onPress={onPressed} // - would work if no arguments required.
onPress={onPressed(argument)} // - will get fired on component render
onPress={()=> onPressed(argument)} // - will work as expected on button press
onPress={()=> { // - will work as expected on button press
// Multiple lines of code
onPressed(argument);
anotherFunction();
}
};
In your MainMap you are doing everything correctly, just uncomment the
// id={itemdata.item.id}
In PlaceInput, just one small change:
<TouchableOpacity onPress={() => this.props.onDelete(this.props.id)}>
<Ionicons name='md-car' size={25} style={{alignSelf: 'center'}} />
</TouchableOpacity>
If you don't add ()=> to your onPress, the function gets called immediately, that's why you see such behaviour.
Your numOfInput is just a list of numbers, so instead of using item.id-s use item directly.
Here:
const items = this.state.numOfInput.filter(item => item !== inputId)
And here
<PlaceInput
key={itemData.item}
// id={itemData.item}
...
/>

Categories

Resources