in DropDownPicker onChangeValue is not triggering - ios

I'm using DropDownPicker in react native but onChangeValue event is not triggering.
I have used onChange and onChangeItem already. Trying to follow this https://hossein-zare.github.io/react-native-dropdown-picker-website/docs/usage#onchangevalue but its not working. Please help me out.
Below is the code:
import React, { useEffect, useState } from 'react';
import {View, Text, Button, TextInput, FlatList, ActivityIndicator, StyleSheet, Image} from 'react-native';
import filter from 'lodash.filter';
import DropDownPicker from 'react-native-dropdown-picker';
const CarList = () => {
const [isLoading, setIsLoading] = useState(false);
const [data, setData] = useState([]);
const [error, setError] = useState(null);
const [query, setQuery] = useState('');
const [fullData, setFullData] = useState([]);
const [selected, setSelected] = useState("");
const [open, setOpen] = useState(false);
const [childOpen, setChildOpen] = useState(false);
const [filterOption, setfilteroption] = useState([
{label: 'Color', value: 'Color'},
{label: 'Model', value: 'Model'},
{label: 'Year', value: 'Year'}
]);
const [value, setValue] = useState(null);
const [childvalue, setChildValue] = useState([]);
useEffect(() => {
setIsLoading(true);
fetch(`https://myfakeapi.com/api/cars/?seed=1&page=1&results=20`)
.then(response => response.json())
.then(response => {
setData(response.cars);
setFullData(response.cars);
setIsLoading(false);
})
.catch(err => {
setIsLoading(false);
setError(err);
});
}, []);
if (isLoading) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<ActivityIndicator size="large" color="#5500dc" />
</View>
);
}
if (error) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text style={{ fontSize: 18}}>
Error fetching data... Check your network connection!
</Text>
</View>
);
}
const handleSearch = text => {
const formattedQuery = text.toLowerCase();
const filteredData = filter(fullData, user => {
return contains(user, formattedQuery);
});
setData(filteredData);
setQuery(text);
};
const contains = ({ car, car_model,car_color }, query) => {
if (car.toLowerCase().includes(query) || car_model.toLowerCase().includes(query) || car_color.toLowerCase().includes(query)) {
return true;
}
return false;
};
const color = [...new Set(data.map((item) => item.car_color))];
const model = [...new Set(data.map((item) => item.car_model))];
const year = [...new Set(data.map((item) => item.car_model_year))];
//this is not triggering
const changeSelectOptionHandler = (value) => {
console.log("hi")
setSelected(value);
};
if (selected === "Color") {
setChildValue(color)
} else if (selected === "Model") {
setChildValue(model)
} else if (selected === "Year") {
setChildValue(year)
}
function renderHeader() {
return (
<View
style={{
backgroundColor: '#fff',
padding: 10,
marginVertical: 10,
borderRadius: 20
}}
>
<TextInput
autoCapitalize="none"
autoCorrect={false}
clearButtonMode="always"
value={query}
onChangeText={queryText => handleSearch(queryText)}
placeholder="Search"
style={{ backgroundColor: '#fff', paddingHorizontal: 20 }}
/>
<DropDownPicker onChangeItem={changeSelectOptionHandler}
open={open}
value={value}
items={filterOption}
setOpen={setOpen}
setValue={setValue}
setItems={setfilteroption}
dropDownDirection="TOP"
style={{
padding: 5,
margin: 5,
width: 200,
flexDirection: 'row'
// borderRadius: 20
}}
/>
<DropDownPicker
open={childOpen}
items={childvalue}
setOpen={setChildOpen}
setItems={setChildValue}
dropDownDirection="TOP"
/>
</View>
);
}
return (
<View style={styles.container}>
<Text style={styles.text}>Favorite Contacts</Text>
<FlatList
keyboardShouldPersistTaps="always"
ListHeaderComponent={renderHeader}
data={data}
keyExtractor={({ id }) => id}
renderItem={({ item }) => (
<View style={styles.listItem}>
<Image
source={{
uri: 'https://picsum.photos/200',
}}
style={styles.coverImage}
/>
<View style={styles.metaInfo}>
<Text style={styles.title}>{`${item.car} ${
item.car_model
}`}</Text>
<Text>Color: {`${item.car_color}`}</Text>
<Text>Price: {`${item.price}`}</Text>
</View>
</View>
)}
/>
</View>
);
}

I needed to use onSelectItem instead of onChangeValue

The latest version of dropdownpicker
OnChangeValue is not supported.
use this :
onSelectItem={(item) => {console.log(item.value)}}
Note: I am using "react-native-dropdown-picker": "^5.4.2",

Related

Custom map marker showing on android device but not on iOS

I'm building a cross-platform app in React Native Expo, and am using react-native-maps to render a map with custom markers. I'm using the 'icon' prop on the Marker component to render a png image, and in addition to this, the Marker displays a child Text element, as follows:
<Marker
key={i}
coordinate={{
latitude: gig.location.latitude,
longitude: gig.location.longitude,
}}
icon={require('../assets/map-pin-50pc.png')}
onPress={() => {
navigation.navigate("GigDetails", {
venue: gig.venue,
gigName: gig.gigName,
image: gig.image,
blurb: gig.blurb,
isFree: gig.isFree,
genre: gig.genre,
dateAndTime: { ...gig.dateAndTime },
tickets: gig.tickets,
});
}}
>
<Text style={styles.gigInfo_text}>{gig.genre}</Text>
</Marker>
On android devices, the custom marker image and the text are rendered as expected. On iOS devices however, only the text is rendered, and the 'icon' image cannot be seen. Any suggestions as to why?
I tried importing the image and passing it to the icon prop as follows:
import mapPinImage from '../assets/map-pin-50pc.png'
...
...
icon = {mapPinImage}
This didn't work either. I also checked the size of the image which was 41x62 pixels, with a size of 2.41kb - well below apple's maximum size requirements.
For context, here's the entire component that render the map:
import { FC } from "react";
import { useState, useMemo } from "react";
import {
StyleSheet,
Text,
View,
Image,
TouchableOpacity,
Platform,
Dimensions
} from "react-native";
import MapView from "react-native-maps";
import { Marker } from "react-native-maps";
import { mapStyle } from "../util/mapStyle";
import { useGigs } from "../hooks/useGigs";
import { AntDesign } from "#expo/vector-icons";
import { format } from "date-fns";
import { mapProps } from "../routes/homeStack";
import { Switch } from 'react-native-paper'
import mapPinImage from '../assets/map-pin-50pc.png'
type MapScreenNavgationProp = mapProps['navigation']
interface Props {
navigation: MapScreenNavgationProp
}
const GigMap:FC<Props> = ({ navigation }):JSX.Element => {
const [selectedDateMs, setSelectedDateMs] = useState<number>(Date.now());
const [isSwitchOn, setIsSwitchOn] = useState(false);
const gigs = useGigs();
//generates current date in format DD/MM/YYYY
const selectedDateString:string = useMemo(() => {
const formattedDate = format(new Date(selectedDateMs),'EEE LLL do Y')
return formattedDate
}, [selectedDateMs]);
const currentDay:string = useMemo(() => {
const formattedDay = format(new Date(selectedDateMs),'EEEE')
return formattedDay
},[selectedDateMs])
const currentWeek:string = useMemo(() => {
const formattedDay = format(new Date(selectedDateMs),'LLLL do Y')
return formattedDay
},[selectedDateMs])
//Filtering through gigs to return only current day's gigs
const gigsToday = gigs.filter((gig) => {
const formattedGigDate = format(new Date(gig.dateAndTime.seconds * 1000), 'EEE LLL do Y')
return formattedGigDate === selectedDateString;
});
const freeGigsToday = gigsToday.filter((gig) => {
return gig.isFree === true
})
const gigsToDisplay = isSwitchOn ? freeGigsToday : gigsToday
//increments date by amount
const addDays = (amount:number):void => {
setSelectedDateMs((curr) => curr + 1000 * 60 * 60 * 24 * amount);
};
const onToggleSwitch = () => setIsSwitchOn(!isSwitchOn);
return (
<View style={styles.container}>
<View testID="gigMapHeader" style={styles.headerText}>
<Text style={styles.headerText_main}>{currentDay}</Text>
<Text style={styles.headerText_sub}>{currentWeek}</Text>
</View>
<View style={styles.imageText}>
<Text style={styles.subHeader}>Tap on the</Text>
<Image
style={styles.image}
source={require("../assets/map-pin-new.png")}
/>
<Text style={styles.subHeader}>
icons on the map to see more gig info
</Text>
</View>
<View style={styles.mapContainer}>
<MapView
initialRegion={{
latitude: -41.29416,
longitude: 174.77782,
latitudeDelta: 0.03,
longitudeDelta: 0.03,
}}
style={styles.map}
customMapStyle={mapStyle}
>
{gigsToDisplay.map((gig, i) => {
return (
<Marker
key={i}
coordinate={{
latitude: gig.location.latitude,
longitude: gig.location.longitude,
}}
icon={require('../assets/map-pin-50pc.png')}
onPress={() => {
navigation.navigate("GigDetails", {
venue: gig.venue,
gigName: gig.gigName,
image: gig.image,
blurb: gig.blurb,
isFree: gig.isFree,
genre: gig.genre,
dateAndTime: { ...gig.dateAndTime },
tickets: gig.tickets,
});
}}
>
<Text style={styles.gigInfo_text}>{gig.genre}</Text>
</Marker>
);
})}
</MapView>
</View>
<View style={styles.buttonOptions}>
<TouchableOpacity onPress={() => addDays(-1)} style={styles.touchable}>
<AntDesign name="caretleft" size={36} color="#000000" />
<Text style={{ fontFamily: "NunitoSans", color: "#000000",marginLeft:'8%' }}>
Previous day
</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => addDays(1)} style={styles.touchable}>
<AntDesign name="caretright" size={36} color="#000000" />
<Text style={{ fontFamily: "NunitoSans", color: "#000000",marginRight:'8%' }}>
Next day
</Text>
</TouchableOpacity>
</View>
<View style = {styles.buttonAndSwitch}>
<TouchableOpacity
onPress={() => navigation.navigate("List")}
style={styles.button}
>
<Text style={styles.buttonText}>List View</Text>
</TouchableOpacity>
<View style = {styles.switch}>
<Switch value={isSwitchOn} onValueChange={onToggleSwitch} color = '#377D8A' />
<Text style = {styles.switch_text}>Free Events</Text>
</View>
</View>
</View>
);
};
const {width:screenWidth, height:screenHeight} = Dimensions.get('window')
const mapWidth = screenWidth * 0.9 //this sets width to 90%
const mapHeight = mapWidth /0.91 //this set height based on the figma map aspect ratio of 0.91
const styles = StyleSheet.create({
container: {
// flexDirection: "column",
// alignItems: "center",
flex:1
},
map: {
height: '100%',
width: '100%'
},
mapContainer:{
marginTop: '5%',
marginHorizontal: 20,
width: mapWidth,
height: mapHeight,
flex:1,
...Platform.select({
ios: {
borderRadius:26,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.3,
shadowRadius: 2,
},
android: {
overflow: 'hidden',
borderRadius:26,
elevation: 4,
}
})
},
gigInfo: {
// backgroundColor: '#68912b',
// marginTop:20
},
gigInfo_text: {
fontSize:10,
color:'black',
fontFamily:'NunitoSans',
paddingTop: 25,
textAlign:'center',
fontWeight:'bold'
},
gigInfo_text_genre: {
color: "white",
fontFamily: "Helvetica-Neue",
transform: [{ translateY: -5 }],
},
headerText: {
color: "black",
fontSize: 25,
marginTop: '0%',
marginLeft: '7%',
fontFamily: "NunitoSans",
marginBottom: 10,
},
headerText_main: {
fontFamily: "NunitoSans",
fontSize:25,
lineHeight:34.1
},
headerText_sub: {
fontFamily:'LatoRegular',
size:14,
lineHeight:16.8
},
callout: {
width: "auto",
height: "auto",
backgroundColor: "azure",
},
buttonOptions: {
flexDirection: "row",
justifyContent: "space-between",
marginTop:'4%',
width:'100%'
},
buttonOptionsText: {
margin: 5,
},
image: {
height:20,
width:14,
marginHorizontal:3
},
imageText: {
flexDirection: "row",
marginLeft:'7%',
marginTop:27
},
touchable: {
flexDirection: "column",
alignItems: "center",
},
subHeader: {
fontFamily: "LatoRegular",
color: "#747474",
size: 12,
lineHeight: 17.04
},
button:{
flexDirection:'column',
width:115,
height:37,
marginLeft:'7%',
backgroundColor:'#377D8A',
borderRadius:8,
justifyContent:'center',
marginTop:'6%'
},
buttonText: {
color:'#FFFFFF',
textAlign:'center',
fontFamily: 'NunitoSans',
fontSize:16,
lineHeight:22
},
buttonAndSwitch:{
flexDirection:'row',
alignItems:'center',
justifyContent:'space-between'
},
switch:{
marginRight:'6%',
transform: [{translateY:7}]
},
switch_text: {
fontFamily: 'LatoRegular',
fontSize:10,
transform:[{translateY:-10}]
}
});
export default GigMap;
Try to replace icon image data props with image Icon as child component to Marker.
<Marker
key={i}
coordinate={{
latitude: gig.location.latitude,
longitude: gig.location.longitude,
}}
icon={require("../assets/map-pin-50pc.png")}
onPress={() => {
navigation.navigate("GigDetails", {
venue: gig.venue,
gigName: gig.gigName,
image: gig.image,
blurb: gig.blurb,
isFree: gig.isFree,
genre: gig.genre,
dateAndTime: { ...gig.dateAndTime },
tickets: gig.tickets,
});
}}
>
<Image
source={require("../assets/map-pin-50pc.png")}
style={{ width: 40, height: 40 }}
/>
<Callout>
<Text style={styles.gigInfo_text}>{gig.genre}</Text>
</Callout>
</Marker>

How to stop echo in iOS side react native audio-record-player?

Below my code for playing voice clip I send here from previous screen
import * as Progress from 'react-native-progress';
import { FontFamily, Fonts } from '../../common/GConstants';
import { Image, SafeAreaView, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import React, { Component } from 'react';
import { heightPercentageToDP as hp, widthPercentageToDP as wp } from 'react-native-responsive-screen';
import AudioRecorderPlayer from 'react-native-audio-recorder-player';
import Colors from '../../common/GColors';
import GColors from '../../common/GColors';
import KeepAwake from 'react-native-keep-awake';
import WaveForm from 'react-native-audiowaveform';
import images from '../../assets/images/index';
import { secondsToTime } from '../../common/GFunction';
export default class ConfirmRecording extends Component {
constructor() {
super();
this.state = {
recordTime: '',
duration: '',
isPlaying: false,
totalDuration: '',
audioPath: '',
currentPositionSec: '',
currentDurationSec: '',
};
this.audioRecorderPlayer = new AudioRecorderPlayer();
}
showProgress = () => {
if (this.state.currentPositionSec / this.state.totalDuration > 1) {
return Math.round(
this.state.currentPositionSec / this.state.totalDuration,
);
} else {
return Math.fround(
this.state.currentPositionSec / this.state.totalDuration,
);
}
};
onStartPlay = async () => {
console.log('START and is playing', this.state.audioPath + "--------" + this.state.isPlaying);
if (this.state.isPlaying) {
this.setState({ isPlaying: false });
this.audioRecorderPlayer.stopPlayer();
this.audioRecorderPlayer.removePlayBackListener();
} else {
const msg = await this.audioRecorderPlayer.startPlayer(
this.state.audioPath,
// 'http://podcasts.cnn.net/cnn/services/podcasting/specials/audio/2007/05/milesobrien.mp3',
);
console.log('Play MSG', msg);
this.audioRecorderPlayer.addPlayBackListener((e) => {
this.setState({
isPlaying: true,
currentPositionSec: Math.round(
Math.round(Math.round(e.current_position / 10) / 100),
),
currentDurationSec: Math.round(Math.round(e.duration / 10) / 100),
playTime: e.current_position,
duration: e.duration,
});
if (e.duration == e.current_position) {
this.setState({ isPlaying: false });
console.log('Stopped');
this.audioRecorderPlayer.stopPlayer();
this.audioRecorderPlayer.removePlayBackListener();
}
return;
});
}
};
componentDidMount = () => {
var audioPath = this.props.navigation.getParam('audioPath');
var duration = this.props.navigation.getParam('duration');
console.warn("Data from prevciouyas screen", audioPath + "--------" + duration)
this.setState({
audioPath: audioPath,
duration: duration
});
}
componentWillUnmount = () => {
this.audioRecorderPlayer.stopPlayer();
this.audioRecorderPlayer.removePlayBackListener();
this.setState({
audioPath: '',
isPlaying: false
});
}
render() {
return (
<SafeAreaView style={style.mainContainer}>
<View style={style.audioView}>
<Text style={style.audioViewText}>Confirm Recording</Text>
<View style={{ marginTop: hp(2) }}>
<View style={style.secondWaveView}>
<WaveForm
style={style.WaveForm}
source={{ uri: this.state.audioPath }} // not work
stop={this.state.isPlaying}
play={this.state.isPlaying}
// autoPlay={true}
waveFormStyle={{ waveColor: Colors.gray, scrubColor: Colors.darkBlue }}
/>
<Text> {secondsToTime(this.state.currentPositionSec)
.m.toString()
.padStart(2, 0) +
':' +
secondsToTime(this.state.currentPositionSec)
.s.toString()
.padStart(2, 0)}</Text>
</View>
<View style={style.secondAudioView}>
<TouchableOpacity
onPress={(event) => {
this.audioRecorderPlayer.stopPlayer();
this.audioRecorderPlayer.removePlayBackListener();
this.setState({ audioPath: '', isPlaying: false }, () => {
// add Imerssion
// this.props.navigation.state.params.a(true),
this.props.navigation.navigate('ImpressionPro')
});
}
}
activeOpacity={.9}>
<Image source={images.sendIcon} />
</TouchableOpacity>
<View style={{ flex: 1 }} />
<TouchableOpacity style={style.icon}
onPress={() => {
this.audioRecorderPlayer.stopPlayer();
this.audioRecorderPlayer.removePlayBackListener();
this.setState({ audioPath: '', isPlaying: false }, () => {
this.props.navigation.pop(2)
});
}}
activeOpacity={.9}>
<Image source={images.deleteCancelBtn} />
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
this.onStartPlay()
.then(() => {
console.log('Playing');
})
.catch((err) => {
console.log('PErr', err);
});
}}
style={style.icon} activeOpacity={.9}>
<Image source={images.playBtn} />
</TouchableOpacity>
</View>
</View>
</View>
<KeepAwake />
</SafeAreaView>
)
}
}
const style = StyleSheet.create({
mainContainer:
{
flex: 1,
backgroundColor: Colors.darkBlue,
justifyContent: 'center',
alignItems: 'center'
},
secondWaveView:
{
marginTop: hp(2),
marginHorizontal: wp(5.5),
flexDirection: 'row',
justifyContent: 'space-between',
},
secondAudioView:
{
flexDirection: 'row',
marginTop: hp(2),
marginStart: wp(5)
},
WaveForm:
{
height: 25,
flex: 1,
},
icon:
{
marginEnd: wp(5)
},
audioView:
{
backgroundColor: Colors.white,
height: "25%",
width: "88%",
alignSelf: 'center',
borderRadius: hp(2),
},
audioViewText:
{
textAlign: 'center',
marginTop: hp(2),
fontSize: Fonts.fontsize20,
marginHorizontal: wp(6),
fontFamily: FontFamily.medium,
color: Colors.textCoffeeColor
},
})
issue was in the waveform for echo ... both were playing same time so thats why issue generated...

How to redirect or load a view depending upon condition in react-native-iap purchase

What I want to achieve is to redirect or show a view upon successful purchase. Purchase is successful but the state variable is not updating inside validateReceiptIos handler.
I checked the validation of the receipt but after that not even able to redirect to another page or load a view on the condition. I am attaching a code snippet below.
const productIds = ['xxx_xx_xx'];
const InAppPurchase = ({ navigation }) => {
const [products, setProducts] = useState([]);
const [purchased, setPurchased] = useState(false);
const [email, setEmail] = useState({
emailText: '',
emailValidity: false,
emailErrorText: null,
});
const [name, setName] = useState({
nameText: '',
nameValidity: false,
nameErrorText: null,
});
const validateUserName = (text) => {
if (text.length < 1) {
setName({ nameText: text, nameValidity: false, nameErrorText: 'Name cannot be empty' });
}
else { setName({ nameText: text, nameValidity: true, nameErrorText: '' }); }
};
const validateEmail = (text) => {
let reg = /^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/;
if (reg.test(text) === false && text.length > 0) {
setEmail({ emailText: text, emailValidity: false, emailErrorText: 'Invalid email' });
} else if (text.length < 1) {
setEmail({ emailText: text, emailValidity: false, emailErrorText: 'Email cannot be empty' });
}
else { setEmail({ emailText: text, emailValidity: true, emailErrorText: '' }); }
};
const validate = async (receipt, purchase) => {
const receiptBody = {
"receipt-data": receipt,
"password": "xxxxxxxxxxxxxxxxxxxxxx"
}
const result = await IAP.validateReceiptIos(receiptBody, true).catch(() => {
}).then((receipt) => {
try {
const renewalHistory = receipt.latest_receipt_info;
const expiration = renewalHistory[renewalHistory.length - 1].expires_date_ms;
// const expiration = renewalHistory[0].expires_date_ms;
let expired = Date.now() > expiration;
if (!expired) {
IAP.finishTransaction(purchase);
setPurchased(true); //***Not updating the state variable***
//navigation.navigate('Success') //***Not even navigate to another page***
} else {
Alert.alert("Purchase expired", "Your subscription has been expired, please resubscribe to continue using the app")
}
} catch (error) {
console.log(error)
}
})
}
useEffect(() => {
IAP.getProducts(productIds).then(res => {
setProducts(res);
})
const purchaseUpdateSubscription = IAP.purchaseUpdatedListener(purchase => {
const receipt = purchase.transactionReceipt;
if (receipt) {
validate(receipt, purchase)
}
})
return () => {
purchaseUpdateSubscription.remove();
}
}, []);
if (purchased) {
return (
<SafeAreaView style={styles.container}>
<View style={styles.containerInner}>
<View style={{ flex: 1, flexDirection: "column" }}>
<View style={styles.logoSuccessSection}>
<Image style={styles.successLogo} source={require('../images/success.png')} />
</View>
<View style={{ flex: 1 }}>
<TouchableOpacity style={styles.button} onPress={() => navigation.navigate('Login')}>
<Text style={styles.signText}>CONTINUE</Text>
</TouchableOpacity>
</View>
</View>
</View>
</SafeAreaView>
)
} else {
return (
<SafeAreaView style={styles.container}>
<View style={styles.containerInner}>
<View style={styles.logoSection}>
<Image style={styles.logo} source={require('../images/logo.jpg')} />
</View>
<View style={styles.headerContainer}>
<Text style={styles.headerText}>PREMIUM ACCESS</Text>
</View>
<View style={styles.featureContainer}>
<ScrollView style={{ flexDirection: 'column', paddingVertical: 20 }}>
<TextInput blurOnSubmit={true} autoCapitalize='none' placeholderTextColor="#736c6c"
style={{ height: 40, borderColor: '#d6d8e1', borderWidth: 1, paddingHorizontal: 10 }} placeholder="Email" onChangeText={(text) => validateEmail(text)} onSubmitEditing={(event) => setEmail({ emailText: event.nativeEvent.text })}
/>
{email.emailValidity === false ? <Text style={styles.errorTextStyle}>{email.emailErrorText}</Text> : null}
<TextInput blurOnSubmit={true} autoCapitalize='none' placeholderTextColor="#736c6c"
style={{ height: 40, borderColor: '#d6d8e1', borderWidth: 1, paddingHorizontal: 10, marginVertical: 5 }} placeholder="Name" onChangeText={(text) => validateUserName(text)} onSubmitEditing={(event) => setName({ nameText: event.nativeEvent.text })}
/>
{name.nameValidity === false ? <Text style={styles.errorTextStyle}>{name.nameErrorText}</Text> : null}
</ScrollView>
</View>
<View>
{products.map((product, i) =>
<TouchableOpacity key={i} style={styles.button} onPress={() => {
if (email.emailValidity === false || name.nameValidity === false) {
Alert.alert(
"Email & Name fields cannot be empty.",
"",
[
{ text: "OK", onPress: () => console.log("OK Pressed") }
],
{ cancelable: false }
);
} else {
IAP.requestSubscription(product.productId);
}
}}>
<Text style={styles.signText}>SUBSCRIBE - $9.99/Month</Text>
</TouchableOpacity>
)}
</View>
</View>
</SafeAreaView>
)
}
}

ipfs.cat returns "undefined" object in React-native

On React-native:
When I add a buffered string(i.e. Buffer(str) ) to IPFS using ipfs.add, the buffered string is added successfully and IPFS returns the hash.
When I try to retrieve the buffered string via ipfs.cat and the hash, ipfs.cat returns "undefined".
On Node.jS and ReactJs:
I do not have this problem. Both ipfs.add and ipfs.cat works.
Is the problem related to pinning in IPFS? or would changing the ipfs-api version in packag.json help?
Any help would be highly appreciated.
Below is the app.js code used for React-Native
import React, {useState, useRef} from 'react';
import {StyleSheet, Text, View, StatusBar, Button} from 'react-native';
const CryptoJS = require('crypto-js');
const ipfsAPI = require('ipfs-api');
// Connceting to the ipfs network via infura gateway
const ipfs = ipfsAPI('ipfs.infura.io', '5001', {protocol: 'https'});
export default function App() {
const [number, setNumber] = useState(0);
const [hash, setHash] = useState(' ');
console.log('printing: ', number);
//console.log('testing:', ipfs);
const handleCaseAdd = () => {
setNumber(1);
// Encrypt
const ciphertext = CryptoJS.AES.encrypt(
JSON.stringify('my message'),
'secret key 1234',
).toString();
console.log(' Ciphertext: ', ciphertext); // 'ciphertext
console.log('Buffered ciphertext: ', Buffer(ciphertext));
// Adding the encrpyted file to IPFS
ipfs.add(Buffer(ciphertext), {pin: true}, (error, result) => {
if (error) {
console.log(error);
return;
}
setHash(result[0].hash);
console.log('File added succesfully');
console.log('IPFS result: ', result);
});
}; // end of the function
const handleCaseGet = fileHash => {
//const fileHash = hash;
console.log('fileHash (before) :', fileHash);
ipfs.files.cat(fileHash, function(err, bufferedCiphertext) {
console.log('fileHash (after) :', fileHash);
console.log('Getting Buffered ciphertext: ', bufferedCiphertext);
});
}; // end of the function
//let confirmed;
//confirmed = true;
return (
<View style={styles.container}>
<View style={styles.first}>
<View style={styles.box1} />
<View style={styles.box2} />
</View>
<View>
<Button title="Add" onPress={handleCaseAdd} />
</View>
<Text> Number: {number} </Text>
<Text> Hash: {hash} </Text>
<View>
<Button title="Get" onPress={handleCaseGet.bind(this, hash)} />
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
//alignItems: "center",
//justifyContent: "center",
paddingTop: StatusBar.currentHeight,
},
first: {
backgroundColor: 'green',
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'flex-start',
},
box1: {
backgroundColor: 'dodgerblue',
width: 50,
height: 50,
//flex: 1,
},
box2: {
backgroundColor: 'gold',
width: 50,
height: 50,
//alignSelf: "flex-start",
},
});
ipfs-api has been deprecated for two years, the replacement is ipfs-http-client - could you please try with that module instead?
https://www.npmjs.com/package/ipfs-http-client

FlatList item click is not rendering this

export default class HistoryScreen extends BaseScreen {
constructor(props){
super(props);
this.state = {
mainListData:[],
listData:[],
searchText:'',
};
}
listRowPressed(item) {
this.props.navigation.navigate('Details', {
checkin: item.data
});
}
render() {
return (
<View style={styles.container}>
<View style={{ flex:1, backgroundColor: '#FFF'}}>
<FlatList
data={this.state.listData}
renderItem={({item}) => <ListComp data={item} />}
keyExtractor={(item, index) => index.toString()}
/>
</View>
</View>
);
}
}
const ListComp = item => (
<TouchableOpacity onPress={() => this.listRowPressed(item)
}>
<View style={styles.row}>
</View>
</TouchableOpacity>
);
I am displaying data in FlatList, however clicking on item gives me this4. listRowPressed is undefined, I tried binding the function too but didn't work. What is wrong in the code?
You have to pass listRowPressed in your ListComp component. Your whole code should be like this :
export default class HistoryScreen extends BaseScreen {
constructor(props) {
super(props);
this.state = {
mainListData: [],
listData: [],
searchText: '',
};
}
listRowPressed = (item) => {
this.props.navigation.navigate('Details', {
checkin: item.data
});
}
render() {
return (
<View style={styles.container}>
<View style={{ flex: 1, backgroundColor: '#FFF' }}>
<FlatList
data={this.state.listData}
renderItem={({ item }) => <ListComp data={item} listRowPressed={this.listRowPressed} />}
keyExtractor={(item, index) => index.toString()}
/>
</View>
</View>
);
}
}
const ListComp = (props) => (
<TouchableOpacity
onPress={() => props.listRowPressed(props.item)}
>
<View style={styles.row}>
{/* Do whatever with props.item here */}
</View>
</TouchableOpacity>
);
Also note that I have converted your method listRowPressed simple function to arrow function.
Try this
<FlatList
data={this.state.listData}
renderItem={this.listComp}
keyExtractor={(item, index) => index.toString()}
/>
listComp = ({item}) => (
return(
<TouchableOpacity onPress={() => this.listRowPressed(item)} >
<View style={styles.row}>
</View>
</TouchableOpacity>
);
);

Resources