I want to integrate flutterwave in my react native application. I downloaded their npm package called flutterwave-react-native and followed their tutorial but still can't do it. I'm using their sample snippet on Github and I'm getting an error that says:
this.usePaymentLink is not a function
I searched everywhere but couldn't find where this.usePaymentLink was defined. You can check out my snippet and tell me what I missed and how this.usePaymentLink can look like.
import React from 'react';
import {View, TouchableOpacity} from 'react-native';
import {FlutterwaveInit} from 'flutterwave-react-native';
class MyCart extends React.Component {
abortController = null;
componentWillUnmout() {
if (this.abortController) {
this.abortController.abort();
}
}
handlePaymentInitialization = () => {
this.setState({
isPending: true,
}, () => {
// set abort controller
this.abortController = new AbortController;
try {
// initialize payment
const paymentLink = await FlutterwaveInit(
{
tx_ref: generateTransactionRef(),
authorization: '[merchant public key]',
amount: 100,
currency: 'USD',
customer: {
email: 'customer-email#example.com',
},
payment_options: 'card',
},
this.abortController
);
// use payment link
return this.usePaymentLink(paymentLink);
} catch (error) {
// do nothing if our payment initialization was aborted
if (error.code === 'ABORTERROR') {
return;
}
// handle other errors
this.displayErrorMessage(error.message);
}
});
}
render() {
const {isPending} = this.state;
return (
<View>
...
<TouchableOpacity
style={[
styles.paymentbutton,
isPending ? styles.paymentButtonBusy : {}
]}
disabled={isPending}
onPress={this.handlePaymentInitialization}
>
Pay $100
</TouchableOpacity>
</View>
)
}
}
so i have been trying to apply it on expo but finally got a breakthrough.
// so i made some little corrections before i could get it running
// this is the code directly from their npm or github
import {PayWithFlutterwave} from 'flutterwave-react-native';
<PayWithFlutterwave
...
onRedirect={handleOnRedirect}
options={{
tx_ref: transactionReference,
authorization: '[merchant public key]',
customer: {
email: 'customer-email#example.com'
},
amount: 2000,
currency: 'NGN',
payment_options: 'card'
}}
/>
// my correction
first of all handleOnRedirect must be a defined function
secondly i removed the three dots (...) before the handleOnRedirect function
then created a function to generate a randomized refrenced no
then i pasted my public flutterwave account key for "merchant public key"
i also pasted my flutterwave account email in place of this 'customer-email#example.com'
import {PayWithFlutterwave} from 'flutterwave-react-native';
const handleOnRedirect = () => {
console.log('sadi')
}
const generateRef = (length) => {
var a = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".split("");
var b = [];
for (var i=0; i<length; i++) {
var j = (Math.random() * (a.length-1)).toFixed(0);
b[i] = a[j];
}
return b.join("");
}
<PayWithFlutterwave
onRedirect={handleOnRedirect}
options={{
tx_ref: generateRef(11),
authorization: 'MY_PUBLIC_KEY',
customer: {
email: 'user#gmail.com'
},
amount: 2000,
currency: 'NGN',
payment_options: 'card'
}}
/>
``
Related
I need your help in little bit query,
i'm trying to render the multiple polyline on a single map,it look like as it (IOS),
it perfectly fine work fine in IOS but not work in android, so my code Snippet it,
import MapboxGL from '#react-native-mapbox-gl/maps';
const MapbBoxDirection = ({shape}: any) => {
const sp = returnOption(shape);
const Poliline = React.useMemo(() => {
return (
<MapboxGL.Animated.ShapeSource
id="routeSource"
buffer={512}
tolerance={1}
lineMetrics={false}
clusterRadius={10}
shape={sp}>
<MapboxGL.Animated.LineLayer
id="routeFill"
style={{
lineColor: '#ff8109',
lineWidth: 10,
lineRoundLimit: 12,
lineCap: 'round',
lineOpacity: 1.84,
}}
/>
</MapboxGL.Animated.ShapeSource>
);
}, [shape, sp]);
return Poliline;
};
import {featureCollection, lineString as makeLineString} from '#turf/helpers';
///// Make Json
export const returnOption = (res): any => {
const feature = res.map((item: any, index: any) => {
if (item[`Route${index}`]?.length > 2) {
return makeLineString(item[`Route${index}`]);
}
});
const featureCollectiondata = featureCollection(feature);
return featureCollectiondata;
};
it's work fine in IOS but not work in android,
i'm also trying to make a json manually without truf helper, i'm facing same problem.
So would you please help me How i can resolve it for android,
one more thing is SINGLE route work fine for both platform so when i'm trying to use featurecollection json it create problem,
Please I'm very Thankful to you,
After a lot a effort i got the Solution Sometime undefined and null is generate default Therefor route line not render on android, but ios it will handle it by default So
export const returnOption = async (res: any, setShape: any) => {
const feature = await Promise.all(
res.map(async (item: any, index: any): Promise<any> => {
if (item[`Route${index}`]?.length > 1) {
// return makeLineString(item[`Route${index}`]);
return {
type: 'Feature',
properties: {
prop0: 'value0',
prop1: 0.0,
},
geometry: {
type: 'LineString',
coordinates: item[`Route${index}`],
},
};
}
}),
);
const RemoveUndefined = feature?.filter(item => item !== undefined);
setShape({
type: 'FeatureCollection',
features: RemoveUndefined,
});
};
finally I have achieve the solution.
I'm building an app with react-navigation-4.2.1. The app has multiple stack navigators. So there are a lots of navigation.push('Routename') calls.
Trouble is when the control surface (i.e. TouchableOpacity) is tapped rapidly multiple times (first one, and the rest during screen transition) I end up pushing multiple screens into the stack. Is there a way to restrict the surface to the first tap/call of push()?
The component below is what i use to make things touchable. it handle multiple touches in small period of time.
Use component below instead of TouchableOpacity. wrap any thing you want with this component and it will be touchable.
<SafeTouch
onPress={...}
>
<Text> hey! im a touchable text now</Text>
</SafeTouch>
The component below is written used TypeScirpt.
every touch within 300ms after first touch will be ignored(thats where help you with your problem).
import * as React from 'react'
import { TouchableOpacity } from 'react-native'
interface ISafeTouchProps {
onPress: () => void
onLongPress?: () => void
onPressIn?: () => void
onPressOut?: () => void,
activeOpacity?: number,
disabled?: boolean,
style: any
}
export class SafeTouch extends React.PureComponent<ISafeTouchProps> {
public static defaultProps: ISafeTouchProps = {
onPress: () => { },
onLongPress: () => { },
onPressIn: () => { },
onPressOut: () => { },
disabled: false,
style: null
}
private isTouchValid: boolean = true
private touchTimeout: any = null
public constructor(props: ISafeTouchProps) {
super(props)
{// Binding methods
this.onPressEvent = this.onPressEvent.bind(this)
}
}
public render(): JSX.Element {
return (
<TouchableOpacity
onPress={this.onPressEvent}
onLongPress={this.props.onLongPress}
onPressIn={this.props.onPressIn}
onPressOut={this.props.onPressOut}
activeOpacity={this.props.activeOpacity}
disabled={this.props.disabled}
style={[{minWidth: 24, minHeight: 24}, this.props.style]}
>
{
this.props.children
}
</TouchableOpacity>
)
}
public componentWillUnmount() {
this.clearTimeoutIfExists()
}
private onPressEvent(): void {
requestAnimationFrame(() => {
if (this.isTouchValid === false) {
return
}
this.isTouchValid = false
this.clearTimeoutIfExists()
this.touchTimeout = setTimeout(() => {
this.isTouchValid = true
}, 300)
if (typeof this.props.onPress === 'function') {
this.props.onPress()
}
})
}
private clearTimeoutIfExists(): void {
if (this.touchTimeout != null) {
clearTimeout(this.touchTimeout)
this.touchTimeout = null
}
}
}
This is the proper behavior for Push and it is not a bug if you want
to avoid the duplicate screen on double tab you can just use navigation.navigate.
To avoid pushing the screen more than once when clicking in the same button in a short span of time, I created a generic hook to avoid running a function more than once (accepting an interval to allow run again):
export const useCallOnce = <T extends unknown[], K>(
fn: (...args: T) => K,
allowAfter?: number,
) => {
const ref = React.useRef<number | undefined>();
const resultFn = (...args: T) => {
const now = new Date().getTime();
if (!ref.current || (allowAfter && ref.current + allowAfter < now)) {
ref.current = now;
return fn(...args);
}
};
return resultFn;
};
Then, you can just call it as in the following example:
const navigation = useNavigation<NativeStackNavigationProp<{ ExampleScreen: undefined }>>();
const push = useCallOnce(() => navigation.push('ExampleScreen'), 500);
// just call on the button click event as: onSomeEvent={() => push()}
You can create a generic button component that accept the push parameters with the hook above, similar to the example, and use this button whenever you want a button to navigate between pages.
I'm in trouble I'm trying to pass information that gets from an api rest that's in a component A and store it in a variable of a B component
i've dealt with this:
Componente A:
data: () => {
return {
server: []
};
}
axios
.post("http://0.tcp.ngrok.io:13601//accountmanagement/login", LogInUser)
.then(res => {
this._UserLogin = res.data;
if (
this._UserLogin.credencial.rol.id_rol == 1 &&
this._UserLogin.credencial.correo == LogInUser.correo
) {
this.$router.push("admin");
} else if (
this._UserLogin.credencial.rol.id_rol == 2 &&
this._UserLogin.credencial.correo == LogInUser.correo
) {
this.$router.push("usuario");
this.server = this._UserLogin
//here I try to send the already verified user to another
component clear the request returns me a json if correct if
the registration is correct:
EventBus.$emit('serverSelected', this.server);
}
})
.catch(resError => {
alert(
"El servidor es en mantenimiento por favor intente mas tarde" +
resError
);
});
Component B:
data: () => {
return {
server: []
};
}
created() {
EventBus.$on(
"serverSelected",
function(serve) {
this.server = serve;
console.log("The person is: ", this.server);
}.bind(this)
);
}
including this does not show me any error or print me the information of the record that I try to send by eventBus.emit
Call eventBus:
import eventBus from '../../evenbus'
evenbus content:
import Vue from 'vue';
export const EventBus = new Vue();
I am using react-native-testing-library - https://callstack.github.io/react-native-testing-library/docs/getting-started
I have a <SegmentedControlIOS> - https://facebook.github.io/react-native/docs/segmentedcontrolios
I want to pres the first segment. I am doing this:
const testID = "SegmentedControl";
const stub = jest.fn();
const values = [{ label: "foo" }];
const { getByTestId } = render(
<SegmentedControlIOS values={['foo', 'bar']} onChange={stub} testID={testID} />
);
expect(() => {
getByTestId(testID);
}).not.toThrow();
fireEvent(getByTestId(testID), "change ", {
nativeEvent: {
value: values[0],
selectedSegmentIndex: 0,
},
});
However I get the error:
No handler function found for event: "change "
Screenshot below. Anyone know how to press different segments in <SegmentedControlIOS>?
fireEvent(element: ReactTestInstance, eventName: string, ...data:
Array): void
The change function is located in the fireEvent object. Here's how to use it:
Version 5 or later:
fireEvent.change(getByTestId(testID), { target: { value: values[0],selectedSegmentIndex: 0 } });
Version 5 or before:
const input = getByTestId(testID);
input.value = values[0];
input.selectedSegmentIndex = 0;
fireEvent.change(input);
If you want to check the onChange function of SegmentedControlIOS,
using fireEvent with native events that aren't already aliased by the fireEvent api.
// you can omit the `on` prefix
fireEvent(getByTestId(testID), 'onChange');
A solution was posted here, I didn't try it yet, but it looks more right I think - https://github.com/callstack/react-native-testing-library/issues/220#issuecomment-541067962
import React from "react";
import { SegmentedControlIOS } from "react-native";
import { fireEvent, render } from "react-native-testing-library";
const testID = "SegmentedControl";
const stub = jest.fn();
const values = [{ label: "foo" }];
const { getByTestId } = render(
<SegmentedControlIOS
values={["foo", "bar"]}
onChange={stub}
testID={testID}
/>,
);
it("sends events", () => {
fireEvent(getByTestId(testID), "onChange", {
nativeEvent: {
value: values[0],
selectedSegmentIndex: 0,
},
});
});
I have a simple query auto-generated from aws AppSync, and I'm trying to use the Connect Component, with a FlatList and use a TextInput to filter and auto-update the list. But I confess I didn't found out a way to do that... any hints?
Tried to find more information about this without success...
Auto-Generated query:
export const listFood = `query ListFood(
$filter: ModelFoodFilterInput
$limit: Int
$nextToken: String
) {
listFood(filter: $filter, limit: $limit, nextToken: $nextToken) {
items {
id
name
description
...
My current code, which I don't quite know where to place my filter value:
<Connect query={graphqlOperation(queries.listFood)}>
{
( { data: { listFood }, loading, error } ) => {
if(error) return (<Text>Error</Text>);
if(loading || !listFood) return (<ActivityIndicator />);
return (
<FlatList
data={listFood.items}
renderItem={({item}) => {
return (
<View style={styles.hcontainer}>
<Image source={{uri:this.state.logoURL}}
style={styles.iconImage}
/>
<View style={styles.vcontainer}>
<Text style={styles.textH3}>{item.name}</Text>
<Text style={styles.textP}>{item.description}</Text>
</View>
</View>
);
}}
keyExtractor={(item, index) => item.id}
/>
);
}
}
</Connect>
What I aim is mainly to filter by item.name, refreshing the list while typing from a TextInput, probably going somewhere on the $filter variable...
Ok, I think I've figured out the usage with the AWS AppSync Out-of-the-box queries...
query MyFoodList{
listFood(
filter: {
name: {
contains:"a"
}
}
) {
items {
id
name
}
}
}
And it is finally working properly with this disposition on my react-native code:
<Connect query={ this.state.filter!=="" ?
graphqlOperation(queries.listFood, {
filter: {
name: {
contains: this.state.filter
}
}
})
:
graphqlOperation(queries.listFood)
}>
I still didn't manage to make the sort key work yet... will try a little more and open another topic for it if I didn't get anything...
This is filter in use in React / Javascript:
const [findPage, setFindPage] = useState('') // setup
async function findpoints() {
// find user & page if exists read record
try {
const todoData = await API.graphql(graphqlOperation(listActivitys, {filter : {owner: {eq: props.user}, page: {eq: action}}}))
const pageFound = todoData.data.listActivitys.items // get the data
console.log('pageFound 1', pageFound)
setFindPage(pageFound) // set to State
} catch (err) {
console.log(err)
}
}
The async / wait approach means the code will try to operate, and move on to other areas of your code putting data into findPage through setFindPage when and if it finds data