Hello,
Thank you for this library 🥇 I would like to propose another interesting feature to this library.
Description
Image the case, when the library is in invisible state and I would like to display the captcha, once user clicked on submit button in the form. When the submission is completed, then we can make an api call to apply the changes. So far I need to handle it using the callback, which is not the cleanest way to do it. Hence I would like to improve it using async/await handle
Posible implementation
Create a ref, which will be responsible for storing the promise
const $promiseToken = useRef<{
resolve: (value: GetToken | PromiseLike<GetToken>) => void;
reject: (arg: any) => void;
} | null>();
Move code to the separate method. It will be used in both places
const onOpen = useCallback(() => {
setVisible(true);
setLoading(true);
$isClosed.current = false;
}, []);
Add new async method getToken, which will be responsible for opening the modal and fetching the token
This promise will be stored in the ref called $promiseToken
useImperativeHandle(
ref,
() => ({
open: () => {
onOpen();
},
close: handleClose,
getToken: () => {
onOpen();
return new Promise<GetToken>(
(resolve, reject: (arg: any) => void) => {
$promiseToken.current = { resolve, reject };
}
);
},
}),
[handleClose, onOpen]
);
Handle this promise in handleMessage method
const handleMessage = useCallback(
(content) => {
try {
const payload = JSON.parse(content.nativeEvent.data);
if (payload.close) {
if (isInvisibleSize) {
handleClose();
}
}
if (payload.load) {
handleLoad(...payload.load);
}
if (payload.expire) {
//@ts-ignore
onExpire?.(...payload.expire);
}
if (payload.error) {
handleClose();
//@ts-ignore
onError?.(...payload.error);
$promiseToken?.current?.reject(payload.error);
}
if (payload.verify) {
handleClose();
//@ts-ignore
onVerify?.(...payload.verify);
const token = payload?.verify?.[0] || '';
$promiseToken?.current?.resolve({ token: token });
}
} catch (err) {
$promiseToken?.current?.reject(err);
}
},
[onVerify, onExpire, onError, handleClose, handleLoad, isInvisibleSize]
);
After everything, we need to clean up a little bit to avoid memory leak
React.useEffect(() => {
return () => {
$promiseToken.current = null;
};
}, []);
Before
const App = () => {
const size = 'normal';
const [key, setKey] = useState('<none>');
const $recaptcha = useRef();
const handleOpenPress = useCallback(() => {
$recaptcha.current.open();
}, []);
const handleClosePress = useCallback(() => {
$recaptcha.current.close();
}, []);
useState(() => {
// handle submit here (api call), which is not the best solution. I would prefer to have it all at one place
},[key])
return (
<>
<StatusBar barStyle="dark-content" />
<SafeAreaView style={styles.safeArea}>
<View
contentInsetAdjustmentBehavior="automatic"
style={styles.container}>
<Button onPress={handleOpenPress} title="Open" />
<Text>Token: {key}</Text>
<Text>Size: {size}</Text>
</View>
<Recaptcha
ref={$recaptcha}
lang="en"
headerComponent={<Button title="Close" onPress={handleClosePress} />}
siteKey="6LejsqwZAAAAAGsmSDWH5g09dOyNoGMcanBllKPF"
baseUrl="http://127.0.0.1"
size={size}
theme="light"
onLoad={() => alert('onLoad event')}
onClose={() => alert('onClose event')}
onError={(err) => {
alert('onError event');
console.warn(err);
}}
onExpire={() => alert('onExpire event')}
onVerify={(token) => {
alert('onVerify event');
setKey(token);
}}
/>
</SafeAreaView>
</>
);
};
After
const App = () => {
const size = 'normal';
const [key, setKey] = useState('<none>');
const $recaptcha = useRef();
const handleOpenPress = useCallback(() => {
const response = await $recaptcha?.current?.getToken();
if (response?.token) {
// do some api calls etc
} else {
// do some api calls etc
Alert.alert('Title', 'Something went wrong');
} }, []);
const handleClosePress = useCallback(() => {
$recaptcha.current.close();
}, []);
return (
<>
<StatusBar barStyle="dark-content" />
<SafeAreaView style={styles.safeArea}>
<View
contentInsetAdjustmentBehavior="automatic"
style={styles.container}>
<Button onPress={handleOpenPress} title="Open" />
<Text>Token: {key}</Text>
<Text>Size: {size}</Text>
</View>
<Recaptcha
ref={$recaptcha}
lang="en"
headerComponent={<Button title="Close" onPress={handleClosePress} />}
siteKey="6LejsqwZAAAAAGsmSDWH5g09dOyNoGMcanBllKPF"
baseUrl="http://127.0.0.1"
size={size}
theme="light"
onLoad={() => alert('onLoad event')}
onClose={() => alert('onClose event')}
onError={(err) => {
alert('onError event');
console.warn(err);
}}
onExpire={() => alert('onExpire event')}
onVerify={(token) => {
alert('onVerify event');
setKey(token);
}}
/>
</SafeAreaView>
</>
);
};
WDYT about above approach ? Feel free to comment.
Hello,
Thank you for this library 🥇 I would like to propose another interesting feature to this library.
Description
Image the case, when the library is in invisible state and I would like to display the captcha, once user clicked on submit button in the form. When the submission is completed, then we can make an api call to apply the changes. So far I need to handle it using the callback, which is not the cleanest way to do it. Hence I would like to improve it using async/await handle
Posible implementation
Create a ref, which will be responsible for storing the promise
Move code to the separate method. It will be used in both places
Add new async method getToken, which will be responsible for opening the modal and fetching the token
This promise will be stored in the ref called
$promiseTokenHandle this promise in
handleMessagemethodAfter everything, we need to clean up a little bit to avoid memory leak
Before
After
WDYT about above approach ? Feel free to comment.