Pass a couple of values in RadioGroup - react-native

Used react-native-flexi-radio-button https://github.com/thegamenicorus/react-native-flexi-radio-button for radio buttons which is awesome but wondering if other values can be passed like index and value props.
For instance Here we can get the selected index and selected value. But I wonder whether I can pass other props (like id from json below) to the radioGroup as well too. I want to pass the id as well. How can I do that?
onSelect(index, value) {
console.log('selected index and value', index + value);
}
<View style={styles.border}>
<RadioGroup
onSelect={(index, value) => this.onSelect(index, value)}
>
{this.state.foodList.map(item1 => {
return (
<RadioButton value={item1.food}>
<Text>{item1.food}</Text>
</RadioButton>
);
})}
</RadioGroup>
</View>
Json data
{"foodList": [
{
"id": 40,
"food": "Bagels",
},
{
"id": 27,
"food": "Beverage",
},
{
"id": 5,
"food": "Burger",
}
]}

Related

React Native: How to implement 2 columns of swipping cards?

I am trying to implement a scrollable list of cards in 2 columns. The cards should be swipe-able left or right out of the screen to be removed.
Basically, it should be like how the Chrome app is showing the list of tabs currently, which can be swiped away to be closed. See example image here.
I am able to implement the list of cards in 2 columns using FlatList. However, I have trouble making the cards swipe-able. I tried react-tinder-card but it cannot restrict swiping up and down and hence the list becomes not scrollable. react-native-deck-swiper also does not work well with list.
Any help is appreciated. Thank you!
I am going to implement a component that satisfies the following requirements:
Create a two column FlatList whose items are your cards.
Implement a gesture handling that recognizes swipeLeft and swipeRight actions which will remove the card that was swiped.
The swipe actions should be animated, meaning we have some kind of drag of the screen behavior.
I will use the basic react-native FlatList with numColumns={2} and react-native-swipe-list-view to handle swipeLeftand swipeRight actions as well as the desired animations.
I will implement a fire and forget action, thus after removing an item, it is gone forever. We will implement a restore mechanism later if we want to be able to restore removed items.
My initial implementation works as follows:
Create a FlatList with numColumns={2} and some additional dummy styling to add some margins.
Create state using useState which holds an array of objects that represent our cards.
Implement a function that removes an item from the state provided an id.
Wrap the item to be rendered in a SwipeRow.
Pass the removeItem function to the swipeGestureEnded prop.
import React, { useState } from "react"
import { FlatList, SafeAreaView, Text, View } from "react-native"
import { SwipeRow } from "react-native-swipe-list-view"
const data = [
{
id: "0",
title: "Title 1",
},
{
id: "1",
title: "Title 2",
},
{
id: "2",
title: "Title 3",
},
{
id: "3",
title: "Title 4",
},
{
id: "4",
title: "Title 5",
},
{
id: "5",
title: "Title 6",
},
{
id: "6",
title: "Title 7",
},
{
id: "7",
title: "Title 8",
},
]
export function Test() {
const [cards, setCards] = useState(data)
const [removed, setRemoved] = useState([])
function removeItem(id) {
let previous = [...cards]
let itemToRemove = previous.find((x) => x.id === id)
setCards(previous.filter((c) => c.id !== id))
setRemoved([...removed, itemToRemove])
}
return (
<SafeAreaView style={{ margin: 20 }}>
<FlatList
data={cards}
numColumns={2}
keyExtractor={(item) => item.id}
renderItem={({ index, item }) => (
<SwipeRow swipeGestureEnded={() => removeItem(item.id)}>
<View />
<View style={{ margin: 20, borderWidth: 1, padding: 20 }}>
<Text>{item.title}</Text>
</View>
</SwipeRow>
)}
/>
</SafeAreaView>
)
}
Notice that we need some kind of property in our objects in order to determine which one we want to remove. I have used a basic id property here, which is quite common using FlatList. If you are retrieving your data from an API which does not provide the same id, then we could just do some preprocessing (normalization) first and add the id prop ourselves.
The initial view looks as follows.
Swiping, let's say the item with 'Title 6' to the right or to the left removes it.
It might be desired to implement the following feature as well.
If the item is in the first column, then only swiping to the left will remove the item.
If the item is in the second column, then only swiping to the right will remove the item.
This is easily implemented using the index param which is passed to the renderItem function and the vx prop of the gestureState passed to the swipeGestureEnded function.
Here is fully working implementation.
import React, { useState } from "react"
import { FlatList, SafeAreaView, Text, View } from "react-native"
import { SwipeRow } from "react-native-swipe-list-view"
const data = [
{
id: "0",
title: "Title 1",
},
{
id: "1",
title: "Title 2",
},
{
id: "2",
title: "Title 3",
},
{
id: "3",
title: "Title 4",
},
{
id: "4",
title: "Title 5",
},
{
id: "5",
title: "Title 6",
},
{
id: "6",
title: "Title 7",
},
{
id: "7",
title: "Title 8",
},
]
export function Test() {
const [cards, setCards] = useState(data)
const [removed, setRemoved] = useState([])
function removeItem(id) {
let previous = [...cards]
let itemToRemove = previous.find((x) => x.id === id)
setCards(previous.filter((c) => c.id !== id))
setRemoved([...removed, itemToRemove])
}
return (
<SafeAreaView style={{ margin: 20 }}>
<FlatList
data={cards}
numColumns={2}
keyExtractor={(item) => item.id}
renderItem={({ index, item }) => (
<SwipeRow
swipeGestureEnded={(key, event) => {
if (event.gestureState.vx < 0) {
if (index % 2 === 0) {
removeItem(item.id)
}
} else if (event.gestureState.vx >= 0) {
if (index % 2 === 1) {
removeItem(item.id)
}
}
}}
disableLeftSwipe={index % 2 === 1}
disableRightSwipe={index % 2 === 0}>
<View />
<View style={{ margin: 20, borderWidth: 1, padding: 20 }}>
<Text>{item.title}</Text>
</View>
</SwipeRow>
)}
/>
</SafeAreaView>
)
}
Since the index is zero based in a FlatList, an item is in the second column if and only if index % 2 === 1 (e.g. an item with index 3 is always in the second column and thus not divisible by 2), on the other hand an item is in the first column if and only if index % 2 === 0 that is index is divisible by 2.
There are several callback function props in the SwipeRowComponent that should be fired in certain situations. However, most of them did not work in my setup and I still have no clue why. I got it to work by using the event.gestureState.vx property which is negative if we swipe to the left and positive (including zero) if we swipe to the right.
It might be desired to implement an undo button as it is quite common in this kind of functionalities. This can be done as follows:
Implement a second state which represents a Queue that holds lastly removed items. The undo button then just pops the lastly removed item.
Here is a fully working implementation with a dummy undo button that achieves exactly that.
import React, { useState } from "react"
import { Button, FlatList, SafeAreaView, Text, View } from "react-native"
import { SwipeRow } from "react-native-swipe-list-view"
const data = [
{
id: "0",
title: "Title 1",
},
{
id: "1",
title: "Title 2",
},
{
id: "2",
title: "Title 3",
},
{
id: "3",
title: "Title 4",
},
{
id: "4",
title: "Title 5",
},
{
id: "5",
title: "Title 6",
},
{
id: "6",
title: "Title 7",
},
{
id: "7",
title: "Title 8",
},
]
export function Test() {
const [cards, setCards] = useState(data)
const [removed, setRemoved] = useState([])
function removeItem(id) {
let previous = [...cards]
let itemToRemove = previous.find((x) => x.id === id)
setCards(previous.filter((c) => c.id !== id))
setRemoved([...removed, itemToRemove])
}
function undoRemove() {
if (removed && removed.length > 0) {
let itemToUndo = removed[removed.length - 1]
setCards([...cards, itemToUndo])
setRemoved(removed.filter((c) => c.id !== itemToUndo.id))
}
}
return (
<SafeAreaView style={{ margin: 20 }}>
<FlatList
data={cards}
numColumns={2}
keyExtractor={(item) => item.id}
renderItem={({ index, item }) => (
<SwipeRow
swipeGestureEnded={(key, event) => {
if (event.gestureState.vx < 0) {
if (index % 2 === 0) {
removeItem(item.id)
}
} else if (event.gestureState.vx >= 0) {
if (index % 2 === 1) {
removeItem(item.id)
}
}
}}
disableLeftSwipe={index % 2 === 1}
disableRightSwipe={index % 2 === 0}>
<View />
<View style={{ margin: 20, borderWidth: 1, padding: 20 }}>
<Text>{item.title}</Text>
</View>
</SwipeRow>
)}
/>
<Button onPress={undoRemove} title="Undo" />
</SafeAreaView>
)
}
Notice that my undo button just appends the removed item to the end of the list. If you want to keep the initial index, then you need to save the old index and push the item to the correct position.
Here is workin snack of my last implementation.

How do I get to a nested array in React Native?

I'm trying to get to the nested array and more specifically to the "dishes" array through the map () method, but to no avail.
const RESTAURANTS = [
{
id: "1",
name: "Filada Family bar",
type: "Bakery",
rating: "5.0",
favorite: true,
hotOffer: true,
hotOfferPromo: require("../images/offers/offer_1.png"),
dishes: [
{
id: "1",
name: "Filada Family bar",
category: "cake",
type: "Asian food",
rating: "5.0",
distance: "0.2 km - $$ -",
image: require("../images/restaurants/restaurant_1.jpg"),
},
],
},
];
I usually only use the following code for the first array, but I need the data from the "dishes" array.
{RESTAURANTS.map((item) => (
<View key={item.id}>
<Text>{item.name}</Text>
</View>
))}
that is just plain javascript. You can either loop restaurants and get dishes or access a restaurant by the index in the array and get the result (or maybe search, filter whatever you need.)
access and index and the dishes property on the object:
{RESTAURANTS[0].dishes.map((item) => (
<View key={item.id}>
<Text>{item.name}</Text>
</View>
))}
Looping restaurants:
{RESTAURANTS.map((restaurant) => {
return restaurant.dishes.map((dish) => (
<View key={dish.id}>
<Text>{dish.name}</Text>
</View>
))
})}
What you need to understand here is that you have an array of objects. When mapping, the item variable means one of these objects that are being looped through and you can access any property like you would in a regular object.

TextInput field not fetching value inside Map function react-native

i want to fetch 'DeliveredQuantity' in Textinput Field, do anyone know solution for this
const [arrayList, setArraylist]= [
{id:0, ExpectedQuantity:10, DeliveredQuantity:7},
{id:1, ExpectedQuantity:19, DeliveredQuantity:9},
{id:2, ExpectedQuantity:11, DeliveredQuantity:11},
{id:3, ExpectedQuantity:45, DeliveredQuantity:30},
]
arrayList.map((items,index)=>{
return
<TextInput value={items.DeliveredQuantity} />
})
Store the array in a state and use it like this
const [arrayList, setArraylist] = React.useState([
{ id: 0, ExpectedQuantity: 10, DeliveredQuantity: 7 },
{ id: 1, ExpectedQuantity: 19, DeliveredQuantity: 9 },
{ id: 2, ExpectedQuantity: 11, DeliveredQuantity: 11 },
{ id: 3, ExpectedQuantity: 45, DeliveredQuantity: 30 },
]);
return (
<View style={styles.container}>
{arrayList.map((items, index) => (
<TextInput value={items.DeliveredQuantity} />
))}
</View>
);
Working Example

fill a picker usin json according to a condition

I can fill a picker using json stocked in state
produits: [{
"code": 11,
"pu": 50,
"ps": 50,
"des": "P 1",
"promo": "1",
}, {
"code": 22,
"pu": 100,
"ps": 100,
"des": "P 2",
"promo": "1",
}, {
"code": 33,
"pu": 80,
"ps": 80,
"des": "P 3",
"promo": "0",
},
{
"code": 44,
"pu": 120,
"ps": 120,
"des": "P 4",
"promo": "1",
},
],
what I want is the same thing but if produits.promo === '1' this item will be shown else it will not be shown, this is my approach but it have an empty picker: whene I click nothing changes :
{<Picker
style={Styles.picker}
selectedValue={this.state.pu}
onValueChange={(itemValue, itemIndex) => this.setState({pu: itemValue, codeProduit: itemIndex+1,})} >
{ this.state.produits.map((item, key)=>
{if (item.promo === "0") {
<Picker.Item label={item.des} value={item.pu} key={item.code} />
}
}
)}
</Picker>}
PS. it works good without If block:
<Picker.Item label={item.des} value={item.pu} key={item.code} />
what's wrong with my approach ?
Just make a new produits array using the filter
render() {
const promoProduits = this.state.produits.filter(item => item.promo === '1');
....
Then render like
{<Picker
style={Styles.picker}
selectedValue={this.state.pu}
onValueChange={(itemValue, itemIndex) => this.setState({pu: itemValue, codeProduit: itemIndex+1,})} >
{
promoProduits.map((item, key)=> (<Picker.Item label={item.des} value={item.pu} key={item.code} />)
}
</Picker>}
I'm not sure if I got you right, but I'll give it a try. For explanation, see code comments.
render Method:
render() {
return (
<View style={styles.container}>
<Picker
selectedValue={this.state.pu}
onValueChange={(itemValue, itemIndex) => this.setState({pu: itemValue, codeProduit: itemIndex+1,})} >
{this.renderPicker()}
</Picker>
</View>
);
}
renderPicker Method:
renderPicker(){
const items = this.state.produits.map((item, key)=> {
// if item.promo === "1" return picker item
if (item.promo === "1") {
// make sure to return Picker Item
return (<Picker.Item label={item.des} value={item.pu} key={item.code} />);
}
});
// return list of pickers
return items;
}
Output:
Working Example:
https://snack.expo.io/#tim1717/trembling-turkish-delight

Section List not displaying

Following the React-Native tutorial and I'm unable to get the data to show.
When I do a console.log my data appears like so:
Array [
Object {
"data": Object {
"address": "8753 2nd Street",
"id": "5507",
"inspection_date": "2019-03-27",
"inspection_time": "07:00:00",
"inspection_time_display": "07.00 AM",
"inspector": "Frank",
},
"key": "5507",
"title": "8753 2nd Street",
},
Object {
"data": Object {
"address": "11445 Paramount ave ",
"id": "5505",
"inspection_date": "2019-03-23",
"inspection_time": "10:30:00",
"inspection_time_display": "10.30 AM",
"inspector": "Fabian Hernandez",
},
"key": "5505",
"title": "11445 Paramount ave ",
},
]
I have the "data" and "title" sections as indicated in most tutorials.
My component is like this:
<Container>
<Header />
<Content>
<SectionList
renderItem={({item, index, section}) => <Text key={index}>{item}</Text>}
renderSectionHeader={({section: {title}}) => (
<Text style={{fontWeight: 'bold'}}>{title}</Text>
)}
sections={this.state.dataSource}
keyExtractor={(item, index) => item + index}
/>
</Content>
</Container>
This is what I think is happening but I'm obviously wrong since something isn't adding up.
Looping through "sections"
renderItem={({item, index, section}) => <Text key={index}>{item}</Text>}
I'm expecting this above to get the "data".
Getting title:
renderSectionHeader={({section: {title}}) => (
<Text style={{fontWeight: 'bold'}}>{title}</Text>
)}
I'm expecting this above to get the "title". What am I missing or doing wrong?
I believe the data key in each of your section objects need to be an array unto itself. Example:
const mySectionedData = [
{
title: 'section 1',
data: [
{address: '123 street', name: 'me'},
{address: '456 street', name: 'you}
]
},
{
title: 'section 2',
data: [
{address: '789 street', name: 'us'}
]
}
]
This then lets you access {title, data} from each of your sections which allows the section list to then render your section header from title, and a list of items from the data array.
Hope that helps!