understad the call to an API - react-native

I am trying to understand an error that I have and that I do not understand.
I have this array:
Array [
Object {
"cost": 0,
"created_at": "2020-12-14T15:54:50Z",
"custom_fields": Object {
"_161_": "4137",
"_162_": "48",
"_163_": "10926",
"_164_": "0",
"_165_": "FLY",
"_166_": "2020-12-14T14:54:37.737Z",
"_167_": "2020-12-31T14:54:37.737Z",
"_168_": "0",
"_171_": "0",
"_300_": "412:00",
"_301_": "45.725556|5.081111",
"_302_": "-27.7078990936|-67.0951004028",
"_303_": "Lyon Saint-Exupéry Airport",
"_304_": "Londres/Belén Airport",
"_310_": "60",
},
"description": "",
"family_id": 0,
"id": 1061,
"incl_tax": 0,
"is_visible": 1,
"name": "Lyon Saint-Exupéry Airport (14/12/2020 à 15:54) > Londres/Belén Airport (31/12/2020 à 15:54)",
"photo": "",
"quantity": 0,
"reference": "",
"stock_status": "1",
"tax_rate_id": 0,
"unit": "",
"updated_at": "2020-12-14T15:54:50Z",
"weight": 0,
},
Object {
"cost": 0,
"created_at": "2020-11-15T01:38:08Z",
"custom_fields": Object {
"_161_": "1373",
"_162_": "30",
"_163_": "4680",
"_164_": "0",
"_165_": "FLY",
"_166_": "2020-11-21T00:37:00.000Z",
"_167_": "2020-11-29T00:37:00.000Z",
"_168_": "0",
"_171_": "0",
"_300_": "190:00",
"_301_": "43.6539083949|-79.65785399079999",
"_302_": "-22.285699844399996|-62.7136993408",
"_303_": "Tarten Heliport",
"_304_": "Santa Victoria Airport",
"_310_": "-480",
},
"description": "",
"family_id": 0,
"id": 896,
"incl_tax": 0,
"is_visible": 1,
"name": "Tarten Heliport (2020-11-21 at 16:37) > Santa Victoria Airport (2020-11-29 at 16:37)",
"photo": "",
"quantity": 0,
"reference": "",
"stock_status": "1",
"tax_rate_id": 0,
"unit": "FLY",
"updated_at": "2020-11-15T01:38:08Z",
"weight": 0,
},
]
It's an array test with 2 products inside (flights) I'm trying to access the filenames, so "name", I don't understand at all why my call returns 'undefined' in console.log when I do
console.log(this.state.name)
I initialize my data in the initListData function, I update the state here so that the name gets the names from my array, I load this function from componentWillMount and then I call the names in my autocomplete.
can someone help me figure out what is wrong, and where i am making the mistake? I need constructed explanations please, there I have a real need for understanding.
Thanks for any leads or help.
Full code :
import React, { Component } from "react";
import {
View,
Text,
StyleSheet,
Button
} from "react-native";
import styles from '../../../assets/styles';
import * as Permissions from "expo-permissions";
import { getProducts } from '../../../src/common/Preferences';
import { Camera } from 'expo-camera';
import i18n from '../../../src/i18n';
import shortid from "shortid";
import {Autocomplete} from "react-native-dropdown-autocomplete";
class Tickets extends Component {
constructor(props) {
super(props);
this.state = {
Press: false,
hasCameraPermission: null,
name: '',
lastScannedUrl:null,
eventSelected: false,
displayArray: []
};
}
initListData = async () => {
let list = await getProducts(1);
if (list) {
this.setState({
displayArray: list,
name: list.name
});
}
console.log('name dans initListData =', list.name)
};
async UNSAFE_componentWillMount() {
this.initListData();
console.log('name dans le state =', this.state.name)
};
componentDidMount() {
this.getPermissionsAsync();
}
getPermissionsAsync = async () => {
const { status } = await Permissions.askAsync(Permissions.CAMERA);
this.setState({ hasCameraPermission: status === "granted" });
};
handleBarCodeScanned = ({ type, data }) => {
this.setState({ Press: false, scanned: true, name: data });
this.props.navigation.navigate('ProductDetails', {name : parseInt(this.state.state.name)})
};
renderBarcodeReader = () => {
const { hasCameraPermission, scanned } = this.state;
if (hasCameraPermission === null) {
return <Text>{i18n.t("scan.request")}</Text>;
}
if (hasCameraPermission === false) {
return <Text>{i18n.t("scan.noaccess")}</Text>;
}
return (
<View
style={{
flex: 1,
...StyleSheet.absoluteFillObject
}}
>
<Camera
onBarCodeScanned={scanned ? undefined : this.handleBarCodeScanned}
barCodeScannerSettings={[Camera.Constants.Type.qr]}
style={{flex:1}}
/>
{scanned && (
<Button
title={"Tap to Scan Again"}
onPress={() => this.setState({ scanned: false })}
disabled={this.state.selectedItem===null}
/>
)}
</View>
);
}
handleSelectItem(item, index) {
const {onDropdownClose} = this.props;
onDropdownClose();
this.setState({eventSelected: true})
console.log(item);
}
render() {
const { hasCameraPermission, scanned, Press } = this.state;
let marker = null;
const {scrollToInput, onDropdownClose, onDropdownShow} = this.props;
//console.log('displayArray', this.state.displayArray, 'name', this.state.name)
return (
<View style={{flex:1}}>
<View style={{width: "100%", zIndex: 100}}>
<Autocomplete
key={shortid.generate()}
containerStyle={{margin: 0, padding: 0, borderBottomColor: 'transparent',}}
inputStyle={{ width: '80%', borderWidth: 1, backgroundColor: '#FFF', opacity: 0.9, borderColor: '#F78400'}}
placeholder={i18n.t("tickets.event")}
placeholderColor="#F78400"
pickerStyle={styles.autocompletePicker}
scrollStyle={styles.autocompleteScroll}
scrollToInput={ev => {}}
handleSelectItem={(item, id) => this.handleSelectItem(item, id)}
onDropdownClose={() => onDropdownClose()}
onDropdownShow={() => onDropdownShow()}
data={this.state.name}
minimumCharactersCount={2}
highlightText
valueExtractor={item => item.name}
rightContent
rightTextExtractor={item => item.properties}
/>
</View>
{this.state.eventSelected ? (
<View>
{this.renderBarcodeReader()}
</View>
) : (
<Text style={{ top: '50%', zIndex:100, color: 'red', fontStyle: 'italic', fontSize: 18}}>{i18n.t("tickets.warning")}</Text>
)}
</View>
);
}
}
export default Tickets;

Related

Expo Camera FaceDetector Landmark Points

In expo-face-detector I have added detectLandmarks as below in Camera
<Camera
style={{ flex: 1 }}
type='front'
onFacesDetected = {faceDetected}
FaceDetectorSettings = {{
mode: FaceDetector.Constants.Mode.accurate,
detectLandmarks: FaceDetector.Constants.Landmarks.all,
runClassifications: FaceDetector.Constants.Classifications.all,
minDetectionInterval: 5000,
tracking: false
}}
>
but data that seems to be print on console.log(faces) within faceDetected function is below only. How to get coordinate of landmraks such as rightEyePosition, leftEyePosition etc as a part of output
object {
"faces": Array [
Object {
"bounds": Object {
"origin": Object {
"x": 68.6222222222222,
"y": 431.6488888888889,
},
"size": Object {
"height": 339.62222222222226,
"width": 220.44444444444446,
},
},
"faceID": -1,
"rollAngle": 0.12390166521072388,
"yawAngle": 0.6850103139877319,
},
],
}
You can try:
detectLandmarks: FaceDetector.Constants.Landmarks.none,
const faceDetected = (faces) => {
console.log(faces)
}

How to pass dynamic ref in react-native-deck-swiper in react native?

I'm not used to using ref, so i have a question. I'm using react-native-deck-swiper to display some cards. People are able to vote by swiping the cards. To be as clear as possible :
My swiper is displayed as an item with other items from multiple
types in my flatlist
My items are rendered conditionally by types of items, if my
item is a swiper type, im displaying a swiper, if it is a simple
text, i'm displaying a text etc...
So I potentially have multiple swipers in my flatlist
Here is the json to display my swipers :
{
"id": 577,
"type": "copernic",
"entity": {
"id": 715,
"str_id": "rCckubRTIDz2D3N5wcKW",
"display_name": "Force Républicaine",
"name": "Force Républicaine",
"title": "Dépense publique",
"description": null,
"type": 2,
"str_type": "Pour / Contre / Neutre",
"is_opened": 1,
"str_is_opened": "Les utilisteurs peuvent soumettre des propositions",
"order_propositions_by": 3,
"display_votes": 1,
"login_to_vote": 0,
"str_login_to_vote": "Les utilisateurs ne doivent pas se connecter pour voter",
"login_to_send_proposition": 1,
"str_login_to_send_proposition": "Les utilisateurs doivent se connecter pour envoyer une proposition",
"begins_at": "2021-03-02T17:45:55.000000Z",
"ends_at": null,
"propositions": [
{
"id": 6572,
"title": "Pensez-vous qu'il faille annuler la dette COVID ?",
"description": "",
"auteur": "Force Républicaine",
"type": 1,
"media_link": null,
"video_frame": null
},
{
"id": 6571,
"title": "Trouvez-vous la qualité des services publics en France à la hauteur du niveau de la dépense publique du pays ?",
"description": "",
"auteur": "Force Républicaine",
"type": 1,
"media_link": null,
"video_frame": null
}
]
},
"is_pinned": 0,
"created_at": "2021-03-18T13:27:03.000000Z"
},
So each swipers could have as a ref, the item.entity.id or the item.entity.id.
My swipers are displaying the item.entity.propositions as cards. Each card have thumbs to vote right, up or left. And I need a ref to do something as swiperRef.current.swipeRight() when we tap on a thumb or to tell the user that every cards from this swiper have been swiped by displaying a message. And now the message is displaying on all swipers and that't not what I want :)
Here's the code for my swiper :
if (
item.type === "copernic" &&
item.entity.str_type === "Pour / Contre / Neutre"
) {
return (
<View style={styles.swipperWrapper} key={item.id}>
{isSwipedAll ? (
<View style={styles.emptyCopernic}>
<View style={styles.emptyCopernicColor} />
<View style={styles.copContainer}>
<Text style={styles.copTitle}>
You have swiped all the cards! Thanx for your participation !
</Text>
</View>
</View>
) : (
<Swiper
ref={useSwiper}
//animateCardOpacity
containerStyle={styles.swiperContainer}
cards={item.entity.propositions}
renderCard={(card, index) => (
<CardCopernic
{...index}
copKey={card.id}
copTitle={card.title}
copDesc={card.description}
strid={strid}
onPressNo={() => swipeLeft(card.id, index)}
onPressMaybe={() => swipeTop(card.id, index)}
onPressYes={() => swipeRight(card.id, index)}
/>
)}
onSwipedLeft={(card) => handleNo(card)}
onSwipedTop={(card) => handleMaybe(card)}
onSwipedRight={(card) => handleYes(card)}
onSwipedAll={onSwipedAllCards}
cardIndex={cardIndex}
stackSize={3}
stackScale={5}
showSecondCard
backgroundColor="white"
cardVerticalMargin={2}
disableBottomSwipe
overlayLabels={{
left: {
title: "Contre",
style: {
label: {
borderColor: "#FF8585",
color: "#FF8585",
borderWidth: 2,
},
wrapper: {
flexDirection: "column",
alignItems: "flex-end",
justifyContent: "flex-start",
marginTop: 30,
marginLeft: -30,
},
},
},
right: {
title: "Pour",
style: {
label: {
borderColor: "#FF8585",
color: "#FF8585",
borderWidth: 2,
},
wrapper: {
flexDirection: "column",
alignItems: "flex-start",
justifyContent: "flex-start",
marginTop: 30,
marginLeft: 30,
},
},
},
top: {
title: "Neutre",
style: {
label: {
borderColor: "#FF8585",
color: "#FF8585",
borderWidth: 2,
},
wrapper: {
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
},
},
},
}}
/>
)}
</View>
);
Here's one of the function to swipe the card to the left, right or top :
swipeLeft = async (cardId, index) => {
console.log("CARDINDEX : ", index);
const cardKey = cardId;
const strid = item.entity.str_id;
const token = await AsyncStorage.getItem("token");
useSwiper.current[strid].swipeLeft(cardId);
const requestOptions = {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Requested-With": "XMLHttpRequest",
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({
vote: "contre",
proposition_id: `${cardKey}`,
consultation_str_id: `${strid}`,
}),
};
try {
let response = await fetch(
`${c.API_URL_DEV}/copernic/vote/add`,
requestOptions
);
let json = await response.json();
if (index === item.entity.propositions.length - 1) {
setSwipedAll(true);
await AsyncStorage.setItem("hasAllSwiped", JSON.stringify(true));
}
return json;
} catch (error) {
console.error(error);
}
};
Any help is appreciated ! I'm a little bit stuck here and not too familiar with refs haha x
And my items are functional components :)
If you need more informations to help, let me know ! :)
Try encapsulating the related swiper code into a component. This will remove the need for dynamic refs and properly encapsulate state.
Something like:
function MySwiper({item}) {
const swiperRef = useRef(null);
const [isSwipedAll, setSwipedAll] = useState(false);
const swipeLeft = useCallback(async (cardId, index) => {
console.log("CARDINDEX : ", index);
const cardKey = cardId;
const strid = item.entity.str_id;
const token = await AsyncStorage.getItem("token");
swiperRef.current.swipeLeft(cardId);
const requestOptions = {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Requested-With": "XMLHttpRequest",
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({
vote: "contre",
proposition_id: `${cardKey}`,
consultation_str_id: `${strid}`,
}),
};
try {
let response = await fetch(
`${c.API_URL_DEV}/copernic/vote/add`,
requestOptions
);
let json = await response.json();
if (index === item.entity.propositions.length - 1) {
setSwipedAll(true);
await AsyncStorage.setItem("hasAllSwiped", JSON.stringify(true)); // TODO: index this somehow by the item
}
return json;
} catch (error) {
console.error(error);
}
}, [item]);
return (
<View style={styles.swipperWrapper} key={item.id}>
{isSwipedAll ? (
<View style={styles.emptyCopernic}>
<View style={styles.emptyCopernicColor} />
<View style={styles.copContainer}>
<Text style={styles.copTitle}>
You have swiped all the cards! Thanx for your participation !
</Text>
</View>
</View>
) : (
<Swiper
ref={useSwiper}
//animateCardOpacity
containerStyle={styles.swiperContainer}
cards={item.entity.propositions}
renderCard={(card, index) => (
<CardCopernic
{...index}
copKey={card.id}
copTitle={card.title}
copDesc={card.description}
strid={strid}
onPressNo={swipeLeft}
onPressMaybe={() => swipeTop(card.id, index)} // UPDATE
onPressYes={() => swipeRight(card.id, index)} // UPDATE
/>
)}
onSwipedLeft={(card) => handleNo(card)} // UPDATE
onSwipedTop={(card) => handleMaybe(card)} // UPDATE
onSwipedRight={(card) => handleYes(card)} // UPDATE
onSwipedAll={onSwipedAllCards}
cardIndex={cardIndex}
stackSize={3}
stackScale={5}
showSecondCard
backgroundColor="white"
cardVerticalMargin={2}
disableBottomSwipe
overlayLabels={...}
/>
)}
</View>
);
}
You'll need to create the other callbacks and fix they storing of state in AsyncStorage to be keyed based on each item.

How to display names from products in API?

I have an array with two products in it. (later, the list will be more complete, for the moment it's to test the autocomplete that I did like this)
I would like to display the list of the names of these two products in an autocomplete input made with the 'react-native-dropdown-autocomplete' package.
I wanted to initialize name in the state, my concern is that when I ask to display this.state.name it returns me undefined since the two names of the two products are different in the array.
Array [
Object {
"cost": 0,
"created_at": "2020-12-14T15:54:50Z",
"custom_fields": Object {
"_161_": "4137",
"_162_": "48",
"_163_": "10926",
"_164_": "0",
"_165_": "FLY",
"_166_": "2020-12-14T14:54:37.737Z",
"_167_": "2020-12-31T14:54:37.737Z",
"_168_": "0",
"_171_": "0",
"_300_": "412:00",
"_301_": "45.725556|5.081111",
"_302_": "-27.7078990936|-67.0951004028",
"_303_": "Lyon Saint-Exupéry Airport",
"_304_": "Londres/Belén Airport",
"_310_": "60",
},
"description": "",
"family_id": 0,
"id": 1061,
"incl_tax": 0,
"is_visible": 1,
"name": "Lyon Saint-Exupéry Airport (14/12/2020 à 15:54) > Londres/Belén Airport (31/12/2020 à 15:54)",
"photo": "",
"quantity": 0,
"reference": "",
"stock_status": "1",
"tax_rate_id": 0,
"unit": "",
"updated_at": "2020-12-14T15:54:50Z",
"weight": 0,
},
Object {
"cost": 0,
"created_at": "2020-11-15T01:38:08Z",
"custom_fields": Object {
"_161_": "1373",
"_162_": "30",
"_163_": "4680",
"_164_": "0",
"_165_": "FLY",
"_166_": "2020-11-21T00:37:00.000Z",
"_167_": "2020-11-29T00:37:00.000Z",
"_168_": "0",
"_171_": "0",
"_300_": "190:00",
"_301_": "43.6539083949|-79.65785399079999",
"_302_": "-22.285699844399996|-62.7136993408",
"_303_": "Tarten Heliport",
"_304_": "Santa Victoria Airport",
"_310_": "-480",
},
"description": "",
"family_id": 0,
"id": 896,
"incl_tax": 0,
"is_visible": 1,
"name": "Tarten Heliport (2020-11-21 at 16:37) > Santa Victoria Airport (2020-11-29 at 16:37)",
"photo": "",
"quantity": 0,
"reference": "",
"stock_status": "1",
"tax_rate_id": 0,
"unit": "FLY",
"updated_at": "2020-11-15T01:38:08Z",
"weight": 0,
},
]
I would like some help figuring out how I can display the product names.
I understood that my error comes from the fact that the API returns several objects (= several products with different names), whereas I have coded so as to manage only one product.
I need some help and explanation please, I'm running around in circles, lost in my code and, frankly, a little desperate.
I want to thank you for any help and explanation.
Thank you
My code :
class Tickets extends Component {
constructor(props) {
super(props);
this.state = {
Press: false,
hasCameraPermission: null,
reference: '',
name:'',
lastScannedUrl:null,
eventSelected: false,
displayArray: []
};
}
initListData = async () => {
let list = await getProducts(1);
if (list) {
this.setState({
displayArray: list,
reference: list.reference,
name: list.name
});
}
// console.log('name dans initListData =', list.name)
// console.log('reference dans initListData =', list.reference)
};
async UNSAFE_componentWillMount() {
this.initListData();
};
componentDidMount() {
this.getPermissionsAsync();
}
getPermissionsAsync = async () => {
const { status } = await Permissions.askAsync(Permissions.CAMERA);
this.setState({ hasCameraPermission: status === "granted" });
};
handleBarCodeScanned = ({ type, data }) => {
this.setState({ Press: false, scanned: true, name: data });
this.props.navigation.navigate('ProductDetails', {name : parseInt(this.state.state.name)})
};
renderBarcodeReader = () => {
const { hasCameraPermission, scanned } = this.state;
if (hasCameraPermission === null) {
return <Text>{i18n.t("scan.request")}</Text>;
}
if (hasCameraPermission === false) {
return <Text>{i18n.t("scan.noaccess")}</Text>;
}
return (
<View
style={{
flex: 1,
...StyleSheet.absoluteFillObject
}}
>
<Camera
onBarCodeScanned={scanned ? undefined : this.handleBarCodeScanned}
barCodeScannerSettings={[Camera.Constants.Type.qr]}
style={{flex:1}}
/>
{scanned && (
<Button
title={"Tap to Scan Again"}
onPress={() => this.setState({ scanned: false })}
disabled={this.state.selectedItem===null}
/>
)}
</View>
);
}
handleSelectItem(item, index) {
const {onDropdownClose} = this.props;
onDropdownClose();
this.setState({eventSelected: true})
//console.log(item);
}
render() {
const { hasCameraPermission, scanned, Press } = this.state;
let marker = null;
const {scrollToInput, onDropdownClose, onDropdownShow} = this.props;
console.log('displayArray', this.state.displayArray, 'name', this.state.name)
console.log('this.state retourne', this.state)
return (
<View style={{flex:1}}>
<View style={{width: "100%", zIndex: 100}}>
<Autocomplete
key={shortid.generate()}
containerStyle={{margin: 0, padding: 0, borderBottomColor: 'transparent',}}
inputStyle={{ width: '80%', borderWidth: 1, backgroundColor: '#FFF', opacity: 0.9, borderColor: '#F78400'}}
placeholder={i18n.t("tickets.event")}
placeholderColor="#F78400"
pickerStyle={styles.autocompletePicker}
scrollStyle={styles.autocompleteScroll}
scrollToInput={ev => {}}
handleSelectItem={(item, id) => this.handleSelectItem(item, id)}
onDropdownClose={() => onDropdownClose()}
onDropdownShow={() => onDropdownShow()}
data={this.state.name}
minimumCharactersCount={2}
highlightText
valueExtractor={item => item.name}
rightContent
rightTextExtractor={item => item.properties}
/>
</View>
{this.state.eventSelected ? (
<View>
{this.renderBarcodeReader()}
</View>
) : (
<Text style={{ top: '33%', zIndex:100, color: 'red', fontStyle: 'italic', fontSize: 18}}>{i18n.t("tickets.warning")}</Text>
)}
</View>
);
}
}
export default Tickets;
What i have found from your Code. I guess the problem is here
data={this.state.name}
Here you have to pass your array.
data={Your_array}

Flatlist inside Flatlist : get data from the parent Flatlist

Im rendering multiple slides and each slide have a list of items.
so I had to render a Flatlist inside Flatlist like this:
<FlatList
ref={(list) => this.ref= list}
data={this.state.buttons} // parent data
keyExtractor={(item) => item.id.toString()}
...
getItemLayout={(data, index)=> (
{
length: wp('100%'),
offset: wp('100%') * index,
index,
borderWidth: 1, borderColor: 'red',
}
)}
showsHorizontalScrollIndicator={false}
renderItem={({item}) => {
let parentData = item;
let myData = this.state.listGifts + '.' + parentData.name;
console.warn('data ', parentData, item);
return (
<View style={{width: wp('100%')}}>
{
this.state.isLoading ?
<ActivityIndicator size='large' style={Styles.styleAI} color={Colors.mainYellow}/>
:
<FlatList
contentContainerStyle={Styles.flatContent}
data={myData}
// keyExtractor={(item) => item.id.toString()}
renderItem={this.renderItem}
removeClippedSubviews={true}
extraData={this.state}
/>
}
</View>
)
}
}
extraData={this.state}
/>
I fetch two JSON :
this.state.buttons >
{
"message": "",
"success": true,
"Category": [
{
"id": 2,
"name": "Peinture"
},
{
"id": 3,
"name": "Cuisine"
},
{
"id": 4,
"name": "Outils"
},
{
"id": 5,
"name": "Electromenager"
}
]
}
this.state.giftsList >
{
"message": "OK",
"success": true,
"Peinture": [
{
"idCadeau": 2,
"Cadeau": "Cadeau1",
"Unites": "100",
},
{
"idCadeau": 3,
"Cadeau": "Cadeau2",
"Unites": "1000",
},
{
"idCadeau": 4,
"Cadeau": "Cadeau3",
"Unites": "50",
}
],
"Cuisine": [
{
"idCadeau": 5,
"Cadeau": "Cadeau4",
"Unites": "200",
},
{
"idCadeau": 6,
"Cadeau": "Cadeau5",
"Unites": "2500",
}
],
"Outils": [
{
"idCadeau": 7,
"Cadeau": "Cadeau6",
"Unites": "100",
}
],
"Electromenager": [
{
"idCadeau": 9,
"Cadeau": "Cadeau7",
"Unites": "500",
}
]
}
for the second Flatlist (the child), I try to get data like this (see code below) :
let myData = this.state.listGifts + '.' + parentData.name;
...
data={myData}
but it doesn't work ! I comment this // keyExtractor={(item) => item.idCadeau.toString()} because it give an error and then it give me an empty list .
**
what I want is set data like this :
**
data={this.state.listGifts.Peinture}
data={this.state.listGifts.Cuisine}
data={this.state.listGifts.Outils}
...
If this.state.listGifts is an object then I believe you mean to do something like this:
let myData = this.state.listGifts[parentData.name];

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