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

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.

Related

React Native how to add button inside Flatlist?

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>
)}

Modal not getting opened on clicking the image of gallery component

I'm trying to open a model when I click on the image component in the gallery. Here I'm not getting the "flagImage" variable updated in onPress method of TouchableOpacity or the modal component is not getting the updated value of "flagImage" when onPress of TouchableOpacity changes its value. I need help here. The modal doesn't open at all whenever I touch the image component. It just does nothing :( Below is the code for gallery.component.js:
import React from 'react';
import { View, Image, ScrollView, TouchableOpacity, Modal, Text } from 'react-native';
import styles from './cameraStyles';
export default ({captures=[], flagImage=true}) => (
<ScrollView
horizontal={true}
style={[styles.bottomToolbar, styles.galleryContainer]}
>
{captures.map(({ uri }) => (
<View style={styles.galleryImageContainer} key={uri}>
<TouchableOpacity
onPress={()=> {
flagImage = !flagImage;
console.log('Touch: "'+flagImage+'"');
}}
>
<Image source={{ uri }} style={styles.galleryImage}/>
</TouchableOpacity>
<Modal visible={flagImage} onPress={() => {console.log('Modal: "'+flagImage+'"');flagImage = !flagImage;}} onRequestClose={() => flagImage = ! flagImage}>
<View>
<Image source={{ uri }} style={styles.galleryImageLarge}/>
</View>
</Modal>
</View>
))}
</ScrollView>
);
You can make use of useState hook to convert the props into a state where you can update them.
import React from 'react';
import { View, Image, ScrollView, TouchableOpacity, Modal, Text } from 'react-native';
import styles from './cameraStyles';
export default ({captures=[], lflagImage=false}) => {
const [flagImage, setflagImage] = React.useState(lflagImage);
return (
<ScrollView
horizontal={true}
style={[styles.bottomToolbar, styles.galleryContainer]}
>
{captures.map(({ uri }) => (
<View style={flagImage?styles.galleryImageContainer:styles.galleryImageContainerView} key={uri}>
<TouchableOpacity
onPress={()=> {
setflagImage(prevData => !prevData)
console.log('Touch: "'+flagImage+'"');
}}
>
<Image source={{ uri }} style={flagImage?styles.galleryImage:styles.galleryImageLarge}/>
</TouchableOpacity>
<Modal visible={flagImage} onRequestClose={() => setflagImage(prevData => !prevData)}>
<View>
<Image source={{ uri }} style={styles.galleryImageLarge}/>
</View>
</Modal>
</View>
))}
</ScrollView>
)
}

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

React Native useState prevent rerendering flatlist

So I have a React Native Flatlist. Then I have a useState which fires when I click on a item in my flatlist. The problem I am facing to right now is that if I click on a item and the useState() fires every item is going to rerender. This is bad because it makes the app extremly slow.
Is there any way to set my State without the FlatList gets rerendered but another view appears (because of the useState())??
My code looks like this:
import React, {useState} from "react"
import {View, Flatlist, Text} from "react-native"
export default const App = () => {
const [x, setX] = useState(false)
return(
<View>
<FlatList
data = {
["-",
"--",
"---",
"----",
"-----",
"------",
"-------",
"--------",
"---------"]
}
renderItem={({item}) => {(
<View>
<TouchableOpacity onPress={() => setX(true)}>
<Text style={{padding: 10,}}>{item}</Text>
</TouchableOpacity>
</View>
)}}
/>
{x == true ? <Button title="It works" onPress={() => console.log("Everything is working")} /> : <View />}
</View>
)
}
In this example the data list is very small. If it get's bigger you really can see a difference
Here are things to consider to make sure that the FlatList won't re-render on state change (see code below):
Make sure that the data being passed is stored or memoized somehow.
Make sure that the callbacks are also memoized.
import React, {useState} from "react"
import {View, Flatlist, Text} from "react-native"
export default const App = () => {
// See 1. above
const [data, setData] = useState([
"-",
"--",
"---",
"----",
"-----",
"------",
"-------",
"--------",
"---------",
]);
const [x, setX] = useState(false)
// See 2. above
const renderItem = useCallback(({ item }) => (
<View>
<TouchableOpacity onPress={() => setX(true)}>
<Text style={{padding: 10,}}>{item}</Text>
</TouchableOpacity>
</View>
), []);
return(
<View>
<FlatList
data={data}
renderItem={renderItem}
/>
{x == true ? <Button title="It works" onPress={() => console.log("Everything is working")} /> : <View />}
</View>
)
}
Here's an idea with memo and separate components:
const App = () => {
const [x,setX] = useState(false);
return (
<View>
<MyFlatList setX={setX}/>
{x == true ? <Button title="It works" onPress={() => console.log("Everything is working")} /> : <View />}
</View>
)
}
and then:
const MyFlatList = React.memo(({setX}) => {
return (
<FlatList
data = {
["-",
"--",
"---",
"----",
"-----",
"------",
"-------",
"--------",
"---------"]
}
renderItem={({item}) => {(
<View>
<TouchableOpacity onPress={() => setX(true)}>
<Text style={{padding: 10,}}>{item}</Text>
</TouchableOpacity>
</View>
)}}
/>
);
});
crawler's answer is very good with recommendations of memoizing the data and the callback, as well.

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

Categories

Resources