Passing a string to navigation.navigate - reactjs

I'm trying to set a menu and I'm trying to pass the path to navigation.navigate as navigation.navigate(menu.path) but it doesn't allow me to pass the route in that way.
So I create the item here with the path as selections.name
export default function Menu_1({ navigation }) {
const [selections, setSelections] = useState([
{ title: 'Normas de utilización de la App', key:'1' , name:'Normas'},
{ title: 'Zonas maritimas', key:'2'}
])
When I try to pass that path to navigation.navigate it doesn't allow to me unless I use Navigation.navigate('Normas')
return (
<View style={globalStyles.container}>
<FlatList
data={selections}
renderItem={({ item })=>(
<TouchableOpacity onPress={() => navigation.navigate()}>
<Card>
<Image
style={{
width: 100,
height: 50,
}}
source={images.images_menu[item.key]} />
<Text style={globalStyles.titleCard}> {item.title} </Text>
</Card>
</TouchableOpacity>
)}
/>
</View>
)
}
is there a way to pass the string from selections.name to navigation.navigate?

If I understood this correctly, you can access the selections.name in the item param of your renderItem prop, like this:
return (
<View style={globalStyles.container}>
<FlatList
data={selections}
renderItem={({ item })=>(
<TouchableOpacity onPress={() => navigation.navigate(item.name)}> // item.name
<Card>
<Image
style={{
width: 100,
height: 50,
}}
source={images.images_menu[item.key]} />
<Text style={globalStyles.titleCard}> {item.title} </Text>
</Card>
</TouchableOpacity>
)}
/>
</View>
)
You can also switch this to whatever you want, navigate(item.key), navigate(item.foo). Just make sure you are keeping the values here
const [selections, setSelections] = useState([
{ title: 'Normas de utilización de la App', key:'1' , name:'Normas'},
{ title: 'Zonas maritimas', key:'2', name: 'Foo'} // missing name
])

Related

React Native : Error in the data part of Flatlist

I tried using Flatlist in order to respond to one of my issue but I got an error on the data= of my Flatlist . I don't rreally undersstand the issue and the error message is not helping ( No overload matches this call. Overload 1 of 2, '(props: FlatListProps<any> | Readonly<FlatListProps<any>>): FlatList<any>', gave the following error. Type '{ id: string; name: string; data: string[]; description: string[]; }' is missing the following properties from type 'readonly any[]': length, concat, join, slice, and 19 more. )
I used flatlist because of this : React Native : Conditional Views.
Here is my code:
<View style={{ flex: 10}}>
{letter.map((letter) => {
const isleetergotdata = letter.data?.length > 0;
if (!isleetergotdata) {
return null;
}
return (
<View
style={{
flex: 1,
flexDirection: "row",
}}
>
<div
ref={fieldRef}
style={{
marginBottom: 100,
}}
>
<Text
style={{
fontSize: 90,
}}
>
{letter.name}
</Text>
</div>
{letter.data?.map((item, index) => {
if (total !== same) {
return (
<FlatList
data={letter} // HERE IS THE ISSUE
numColumns={2}
keyExtractor={(_, index) => index.toString()}
renderItem={({ item }) => {
return (
<View>
<Text>{letter.description[index]}</Text>
</View>
);
}}
/>
);
}
})}
</View>
);
})}
</View>
And here is my data:
const letter = [
{
id: "1",
name: "A",
data: ["Abricot", "Abricot", "Abricot"],
description: [
"Un abricot est un fruit",
"Un abricot est un fruit",
"Un abricot est un fruit",
],
},
//...
{
id: "5",
name: "E",
data: [],
description: [],
},
//...
];
The problem here is that you are providing letter to the FlatList's data prop, but this is not the global letter variable but the one of the local scope of the outer map function. You have given them the same name. Thus, letter in the map function is an object and not an array.
It seems to me that you want to create a FlatList for each object inside the "global" letter variable and provide the description property of each of these objects (which is an array and you are acessing it via the index which is really not necessary).
Thus, you actually only need to use one map and remove the inner map function. I would also rename the local variable letter to something else.
<View style={{ flex: 10}}>
{letter.map((datum) => {
const isleetergotdata = datum.data?.length > 0;
if (!isleetergotdata) {
return null;
}
return (
<View
style={{
flex: 1,
flexDirection: "row",
}}
>
<div
ref={fieldRef}
style={{
marginBottom: 100,
}}
>
<Text
style={{
fontSize: 90,
}}
>
{datum.name}
</Text>
</div>
if (total !== same) {
return (
<FlatList
data={datum.description}
numColumns={2}
keyExtractor={(_, index) => index.toString()}
renderItem={({ item }) => {
return (
<View>
<Text>{item}</Text>
</View>
);
}}
/>
);
}
)
}
</View>
);
})}
</View>
And to be precise here, remove the letter.data?.map((item, index) part completely.
If you need both data and desription in the same FlatList, then you can still leave the inner map function.
<FlatList
data={datum.data}
numColumns={2}
keyExtractor={(_, index) => index.toString()}
renderItem={({ item, index }) => {
return (
<View>
<Text>{datum.description[index]}</Text>
</View>
);
}}
/>
You can get the data from array.
Step:01 Inside API call.
jsonElement["Letter"]
Step:02
const [dataSource, setDataSource] = useState([]);
Step:03
<FlatList horizontal={true} data={dataSource} />
Step:04
{item.id}
₹ {item.name}
When I run your code I face a different error related to the div tag. React-Native has no dom and if you do not have a custom 'div' component, you can not use the div tag. Even if a 'Div' component is in your project, component names should start with a capital letter.

Encountered two children with the same key on FlatGrid('react-native-super-grid)

I am rendering items from API on my application. I used FlatGrid from react-native-suprt-grid instead of using FlatList because I want a grid view of the items. While using FlatGrid I get the error: "Error: Warning: Encountered two children with the same key, .$0_1." FlatGrid has the keyextractor property.
Here is my code :
return(
<View style={{ flex: 1, padding: 24, }}>
<SearchBar round
searchIcon={{size:24}}
platform={Platform.OS}
containerStyle={{backgroundColor: '#FFFFFF'}}
backgroundColor={'#FFFFFF'}
inputStyle={{backgroundColor: '#FFFFFF'}}
placeholder='Search for items...'
cancelButtonTitle='Cancel'
></SearchBar>
{isLoading ? <ActivityIndicator /> : (
<FlatGrid
style={{marginTop:35}}
itemDimension={130}
spacing={10}
data={data}
keyExtractor={(item, index) => {
console.log("index", index)
return index.toString();
}}
renderItem={({ item }) => {
return (
// <Text style={{ flex: 1, backgroundColor: '#ffe4e1' }}>{item.name}</Text>
// <Text style={styles.itemName} > {item.name} </Text>
<View style={styles.gridView}>
<CardView name= {item.name}/>
</View>
)
}}
/>
)}
</View>
)
}
I render my items from an external component CardView.
Your key can be of type integer. You don‘t have to convert it into a string.
And ideally, each item in your data should have a unique id.
Once done, you can then try this:
keyExtractor={(item) => item.id}

Prevent Item Background Color From Changing Flatlist

I have a FlatList that is pulling in contact from a user's phone. I want to give each contact that doesn't have an avatar a random color from an array of hex color codes which I call "CircleColors".
This is what I'm trying:
<FlatList
data={filteredContacts}
renderItem={({ item }) => (
<View key={uuidv4()} style={styles.contactItem}>
<View style={item.avatar && styles.contactAvatar}>
{item.avatar && (
<Image
style={{
borderRadius: 50,
width: 50,
height: 50,
}}
source={{
uri: item.avatar,
}}
/>
)}
{!item.avatar && (
<ContactItem
itemData={item.name}
color={
CircleColors[
Math.floor(Math.random() * CircleColors.length)
]
}
/>
)}
</View>
<View>
<Text style={styles.contactTxt}>{`${item.name}`}</Text>
<Text
style={
item.usernames.length
? styles.contactUser
: styles.noUser
}
>
{item.usernames.length ? `$${item.usernames}` : null}
</Text>
</View>
</View>
)}
/>
And here is the code for the contact item:
const ContactItem = ({ itemData, color }) => {
return (
<View
style={[
styles.userCircle,
{
backgroundColor: color,
},
]}
>
<Text style={styles.userCircleTxt}>
{itemData.substr(0, 1).toUpperCase()}
</Text>
</View>
);
};
The problem is that on scroll, the flatlist rerenders each item, and the colors change each time. Is there a way to persist the original random color given to each item background, even on scroll?
Any help would be greatly appreciated.
Thanks!
the problem come with this line
<View key={uuidv4()} style={styles.contactItem}>
the key always change, you should pass index to key
renderItem={({ item,index }) => (
<View key={index} style={styles.contactItem}>
Pass key as index and dynamic background color styles in array like below -
renderItem={({ item,index }) => (
<View key={index} style={[{item.background},styles.contactItem]}>

error in passing data through navigation in react native

I'm new to react native world and I'm trying to integrate a calendar with a time slot picker, so I'm trying to pass the selected date from the calendar to the slot picker page but I'm having this Error when I press on a date in the calendar and I couldn't fix it.
TypeError: undefined is not an object (evaluating 'navigation.navigate')
This is my calendar function:
const RequestMeeting = ({ navigation }) => {
const [isModalVisible, setModalVisible] = useState(false);
const toggleModal = () => {
setModalVisible(!isModalVisible);
};
return (
<View style={{ margin: 100, }}>
<Button title="Show modal" onPress={toggleModal} />
<Modal isVisible={isModalVisible} avoidKeyboard={true} scrollHorizontal={true} propagateSwipe={true}>
<ScrollView>
<View style={{ margin: 50, backgroundColor: 'gray', borderRadius: 20, padding: 20, margin: 20 }}>
<Text style={styles.heading}>Request to Buy/Rent</Text>
<View style={{ paddingBottom: 10 }}></View>
<View >
<Calendar
onDayPress={(day) => navigation.navigate("Slot", { bookingDate: day })}
style={styles.calendar}
hideExtraDays
theme={{
selectedDayBackgroundColor: 'green',
todayTextColor: 'green',
arrowColor: 'green',
}}
/>
</View>
<Button
buttonStyle={styles.register}
title="Send Buy/Rent request"
/>
<Button
buttonStyle={styles.cancelbtn}
title="Cancel"
onPress={toggleModal}
/>
</View>
</ScrollView>
</Modal>
</View>
);
};
And this is my time slot picker function:
const jsonData = {
"slots": {
"slot1": "9:00am to 9:30am",
"slot2": "9:30am to 10:00am",
"slot3": "10:00am to 10:30am",
"slot4": "10:30am to 11:00am",
"slot5": "11:00am to 11:30am",
"slot6": "11:30am to 12:00pm"
}
}
const Slot = ({ navigation }) => {
const onPressBack = () => {
const { goBack } = navigation
goBack()
}
const slots = jsonData.slots
const slotsarr = Object.keys(slots).map(function (k) {
return (
<View key={k} style={{ margin: 5 }}>
<TouchableOpacity >
<Text>{slots[k]}</Text>
</TouchableOpacity>
</View>)
});
return (
<View style={styles.container}>
<StatusBar barStyle="light-content" />
<View >
<TouchableOpacity onPress={() => onPressBack()}><Text >Back</Text></TouchableOpacity>
<Text ></Text>
<Text ></Text>
</View>
{ slotsarr}
</View>
);
}
This error means that wherever you are rendering RequestMeeting or Slot (whichever one has the error) it's not getting the navigation prop. If it is rendered as a Screen then it will get the prop from the Navigator. If it's not a top-level screen then you need to pass down the prop from a parent or access it with the useNavigation hook.
Docs: Access the navigation prop from any component

How to pass Parent Flatlist's Index value to Child Flatlist's onPress function?

How to pass parent Flatlist's index value to child Flatlist's function so I can use it in function and change value by setState.
So how to pass parent Flatlist's index value to child Flatlist's function so I can use it in function and change value by setState.
It starts with a list that built-in state
constructor(props) {
super(props);
this.state = {
list: [
{
question: 'il veicolo ha la gomma forata?',
answers: [
{
radioButtonValue: false,
text: strings.CONFIRMVIEW_yes,
},
{
radioButtonValue: true,
text: strings.CONFIRMVIEW_no,
},
],
},
]
}
}
checkBoxSelection = (item, index) => {
// if (item.radioButtonValue == index) {
// this.list.answers[index].radioButtonValue = true
// }
console.log(this.state.list[0].answers[index].radioButtonValue)
}
_renderItem = ({ item, index }) => {
return (
<View style={styles.cellView}>
<Text style={styles.questionText}>
{item.question.toUpperCase()}
</Text>
<FlatList
data={item.answers}
horizontal={true}
showsHorizontalScrollIndicator={true}
scrollEnabled={true}
bounces={false}
renderItem={this._renderItemOptions}
/>
{/* <View style={styles.yesNoRadioButtonView}>
<View style={styles.yesChekboxView}>
<TouchableOpacity onPress={ () => {console.log("TEST1"); this.checkBoxSelection()} }>
<Image source={(item.answers == index) ? AppImages.radioOn : AppImages.radioOff} style={styles.radioButton} />
</TouchableOpacity>
<Text style={styles.yesNoText}>
{strings.CONFIRMVIEW_yes}
</Text>
</View>
<View style={styles.noRadioButtonView}>
<TouchableOpacity onPress={() => { this.checkBoxSelection.bind(this) }}>
<Image source={(item.answers == 0) ? AppImages.radioOn : AppImages.radioOff} style={styles.radioButton} />
</TouchableOpacity>
<Text style={styles.yesNoText}>
{strings.CONFIRMVIEW_no}
</Text>
</View>
</View> */}
</View>
)
}
_renderItemOptions = ({ item, index }) => {
return (
<View>
<View style={styles.yesNoRadioButtonView}>
<TouchableOpacity onPress={() => { this.checkBoxSelection(item, index) }}>
<View style={styles.yesChekboxView}>
<Image
source={item.radioButtonValue ? AppImages.radioOn : AppImages.radioOff}
style={styles.radioButton}
/>
<Text style={styles.yesNoText}>
{item.text}
</Text>
</View>
</TouchableOpacity>
</View>
</View>
)
}
render() {
return (
<Container>
<Content style={styles.container}>
<FlatList
data={this.state.list}
showsVerticalScrollIndicator={false}
scrollEnabled={false}
bounces={false}
renderItem={this._renderItem}
/>
</Content>
<SafeAreaView>
<TouchableOpacity
style={[LayoutStyle.appBtn1]}
>
<Text style={[LayoutStyle.appBtnText1]}>
{strings.DAMAGE_SURVEY_comeOn.toUpperCase()}
</Text>
</TouchableOpacity>
</SafeAreaView>
</Container>
)
}
In Parent Flatlist's renderItem function
replace
renderItem = { () => {this.renderItemOptions(item, index)}}
with
renderItem={(childData) => this._renderItemOptions(childData, index)}
and then in child Flatlist's renderItemOption function need to get parentIndex with another name.
_renderItemOptions = ({ item, index }, parentIndex) => {
console.log("hello")
return (
<View>
<View style={styles.yesNoRadioButtonView}>
<TouchableOpacity onPress={() => { this.checkBoxSelection(item, index, parentIndex) }}>
<View style={styles.yesChekboxView}>
<Image
source={item.radioButtonValue ? AppImages.radioOn : AppImages.radioOff}
style={styles.radioButton}
/>
<Text style={styles.yesNoText}>
{item.text}
</Text>
</View>
</TouchableOpacity>
</View>
</View>
)
}
Try updating your renderItem prop in your FlatList to explicitly pass the index
renderItem={({item, index}) => this._renderItemOptions(item, index)}

Resources