React Native get Touched components with PanResponder API - react-native

I'm trying to select multiple elements inside the pan component. I seacrhed a lot and now I can get the scrool coordinates, but with this x and y coordinate values I can't understand which one is selected.
HourComponent.js (so simple just one text)
<View
height={35}
marginVertical={8}
width={Dimensions.get("window").width / 3 }
borderRadius={10}
alignItems="center"
justifyContent="center"
bg={this.props.isSelected ? "green" : "#F0F2F6"}
marginHorizontal={6}
>
<Text>{this.props.hourText}</Text>
</View>;
constructor
constructor(props) {
super(props);
const panResponder = PanResponder.create({
onStartShouldSetPanResponder: (evt, gestureState) => true,
onMoveShouldSetPanResponder: (evt, gestureState) => true,
onPanResponderMove: (event, gesture) => {
var witdh = 110;// I find that with console.log ,the component box sizes
var height = 30;
var x = gesture.moveX / witdh;
var y = gesture.moveY / height;
console.log('gesture.moveY', gesture.moveY);
console.log('x: ' + x + ' y: ' + y);
},
});
this.state = {
hours: [
{isSelected: false, hourText: '10:00'},
{isSelected: false, hourText: '10:20'},
{isSelected: false, hourText: '10:40'},
{isSelected: false, hourText: '11:00'},
{isSelected: false, hourText: '11:20'},
{isSelected: false, hourText: '11:40'},
{isSelected: false, hourText: '12:00'},
{isSelected: false, hourText: '12:20'},
{isSelected: false, hourText: '12:40'},
],
panResponder,
};
}
In render section
<Box
flex={1}
mt={20}
alignItems={"flex-start"}
justifyContent={"center"}
flexDirection={"row"}
flexWrap={"wrap"}
flexDirection="row"
>
{this.state.hours.map((hours, index) => {
return (
<View
style={{
backgroundColor: "red",
}}
{...this.state.panResponder.panHandlers}
>
<TouchableOpacity
style={{ backgroundColor: "blue" }}
onPress={() => {
this.hourSelect(hours, index);
}}
>
<HoursComponent
hoursText={hours.hoursText}
isSelected={hours.isSelected}
hours={hours}
/>
</TouchableOpacity>
</View>
);
})}
</Box>;
Render Result
Console logs
My problem is how to get selected component.I can't make it with coordinates .Thank you
I can't get the selected values ,just can get coordiantes
I'm still having this problem

Related

Error & Warning(React Native) - Event has less arguments than mapping & ANIMATED.EVENT NOW REQUIRES A SECOND ARGUMENT FOR OPTIONS

Code for Animated Flatlist
const scrollY = useRef(new Animated.Value(0)).current;
const keyExtractorItem = useCallback((item) => item.id.toString(), []);
const anEvent = Animated.event(
[
{
nativeEvent: {
contentOffset: {
y: scrollY,
},
},
},
{ useNativeDriver: true }
],
);
<AnimatedFlashList
onScroll={anEvent}
contentContainerStyle={{ paddingTop: StatusBar.currentHeight || 42 }}
data={DATA}
keyExtractor={keyExtractorItem}
renderItem={renderItem}
estimatedItemSize={20}
/>
Error Occured While Scrolling
Event has less arguments than mapping
Warning Shown
ANIMATED.EVENT NOW REQUIRES A SECOND ARGUMENT FOR OPTIONS
Error Solved
const anEvent = Animated.event(
[
{
nativeEvent: {
contentOffset: {
y: scrollY,
},
},
},
],
{ useNativeDriver: true }
);
UseNativeDriver should be below the array.

How can get offset from panResponder

I have an element(red) in the center of Screen and is able for drag and drop. I make it only move Vertical. I want when move/drag the element down of up, get h (new position - default/first position).
How can find h?
onPanResponderMove:
Animated.event([
null,
{
dx: pan.x,
dy: pan.y,
},
],{useNativeDriver: false}),
onPanResponderRelease: () => {
Animated.spring(
pan, // Auto-multiplexed
{ toValue: { x: 0, y: 0 }, useNativeDriver: false } // Back to zero
).start();
},
});
I try this but the element isn't able to drag/move.
onPanResponderMove: (event, gestureState) => {
alert(gestureState.dy)
Animated.event([
null,
{
dx: pan.x,
dy: pan.y,
},
],{useNativeDriver: false})
},

understad the call to an API

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;

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}

Modify header according to one parameter

I was trying to modify my custom header according to one parameter that is in the state from the same component. But I see that it does not work. I can do the same inside the render and it obviously does but how can I do it in the header?
In this case for instance, I would like to change the button for another if itemNumber > 0
...
static navigationOptions = ({ navigation }) => {
return{
title: "Edit Group"+' ',
headerStyle: {
backgroundColor: '#2ca089',
elevation: 0,
shadowOpacity: 0,
borderBottomWidth: 0,
},
headerTintColor: '#fff',
headerRight: (
<Button hasText transparent onPress={() =>
Alert.alert(
"Delete Group",
"Are you sure you want to delete this group? It is a non-reversible action!",
[
{text: 'Yes', onPress: () => console.log('Yes Pressed')},
{text: 'No', onPress: () => console.log('No Pressed'), style: 'cancel'},
],
)
}>
<Text>Delete Group</Text>
</Button>
),
};
}
constructor(props) {
super(props)
this.state = {
dataSource : [],
text : '',
itemNumber : 0,
}
}
...
I understand that because it is a static component it will not be modified dynamically but I do not see how can I do it in another fashion.
Thanks,
I can not see where the answer from TNC implement the callback function inside the headerRight in order to re-update the navigation header which I think it is the problem.
My solution is the following:
The variable which you want to observe is itemNumber, make sure is in the constructor ✅
constructor(props) {
super(props)
this.state = {
dataSource : [],
text : '',
itemNumber : 0,
selectedItems: []
}
}
Then, inside the function which you trigger the event which requires the update for the header add the following code:
triggerFunction = parameters => {
//...
let newValue = 1 //Implement your logic
this.setState(({itemNumber}) => {
this.props.navigation.setParams({itemNumber: newValue})
return {itemNumber: newValue }
});
//...
};
To conclude, on the navigationOption add the following code:
static navigationOptions = ({ navigation }) => {
return{
headerRight:
navigation.getParam('itemNumber', 0) > 0
?
<Button hasText transparent onPress={() =>
Alert.alert(
"Delete User",
"Are you sure you want to delete this user/users? It is a non-reversible action!",
[
{text: 'Yes', onPress: () => console.log('Yes Pressed')},
{text: 'No', onPress: () => console.log('No Pressed'), style: 'cancel'},
],
)
}>
<Text>Delete Users</Text>
</Button>
:
null
};
}
I have got the inspiration from this answer:
https://stackoverflow.com/a/51911736/5288983
I also attach you the documentation where you can understand better the approach:
https://reactnavigation.org/docs/en/headers.html#setting-the-header-title
You can pass multiple params to navigator as:
From Calling Container/Component
this.props.navigation.navigate('navigator-destination', {
title: 'Your Title',
label: 'Extra Params',
callback: callback // Even callback
});
In Called Container/Component
static navigationOptions = ({navigation}) => {
const {state} = navigation;
label = state.params.label;
return {
title: `${state.params.title}`,
headerStyle: {
backgroundColor: '#f4511e',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
};
};
To call callback:
_someMethod = () => {
const {navigation} = this.props;
navigation.state.params.callback(parameters);
navigation.goBack();
};