How to use yield call in React-Native? - react-native

I am implementing fingerprint scanning in my RN app and I found a good tutorial for that but the code there has a syntax which I have never used - yield call(), however, I googled it and couldn't find a proper explanation for it.
Here is the code:
if (isFingerPrintSupported === true) {
yield call(KeychainService.setCredentials, user_name,
JSON.stringify({ password }));
}
Is there something else I can use instead in this case? if not then how can I import this or install in order to make it work?
EDIT(example code added):
componentWillMount() {
let credentials = yield call(KeychainService.getCredentials);
if (credentials && credentials.username)) {
let isFingerPrintSupported = yield call(KeychainService.checkBiometricSupportednEnrolled);
if (isFingerPrintSupported === true) {
// show fingerprint alert on login page
// and authenticate FingerPrint when user touch the sensor
}
} else {
// else don’t show fingerprint option on login
}
}

yield can be used inside a generator function & it helps to pause and resume a function at any time asynchronously. Also Additionally it helps to return value from a generator function.
Check this document for more information.
call is redux-saga effects which help to make asynchronous calls. Check this for more information.
import { call } from 'redux-saga/effects'
function* authorize(user, password) {
try {
const response = yield call(/** Api call */, user, password)
...
} catch(error) {
...
}
}
Note
If you don't want to use yield, you can directly call you API with params using axios or fetch.
Hope this helps you. Feel free for doubts.

Related

Can we overwrite 'expect' method of testcafe's TestController

I am looking for a way to overwrite expect method for TestController. My idea is existing tests whoever used t.expect method, I want to perform additional steps in those cases.
I came up with below sample code but testcafe runtime fails with below error
TypeError: Cannot read property '_expect$' of undefined
sample code attempting to override:
import { Selector } from "testcafe";
fixture`Getting Started`.page`http://devexpress.github.io/testcafe/example`;
test("My first test", async (t) => {
t = modify(t);
await t.typeText("#developer-name", "John Smith").click("#submit-button");
// Use the assertion to check if the actual header text is equal to the expected one
await t
.expect(Selector("#article-header").innerText)
.eql("Thank you, John Smith!");
});
function modify(t) {
let prevExpect = t.expect;
t.expect = (param) => {
console.log("modified expecte has been used");
return prevExpect(param);
};
return t;
}
Also, when using t.click(Selector(...).expect(...), It doesn't use my overwritten expect. How to make it work in the call chain as well?
Technically, it's possible to overwrite the expect method, but please note that this approach may lead to incorrect work and unexpected errors.
You need to modify your modify function as follows:
function modify (t) {
let prevExpect = t.expect;
t.expect = (param) => {
console.log("modified expect has been used");
return prevExpect.call(t, param);
};
return t;
}
As for the t.click(Selector(...).expect(...) issue, you call the expect method of Selector, but Selector does not have the expect method.
You need to add ) after Selector:
await t.click(Selector(...)).expect(...)

Code not executing when awaiting dispatch in for loop

I can not find anything on this so I decided to ask it here.
I am using react-native and redux.
I left the business logic out of the code.
I have this function which calls another function that does an API call.
The function that does the API call needs to access "getState", that's the reason I use dispatch.
const getStuff = (day) => (dispatch) => {
const result = await dispatch(functionThatDoesAPIRequest(day)
}
Then I have this code that loops over days and in some cases needs to do the API call. In the case I was testing it does not need to access the API. I could not find the problem with my code until I placed the line between the if statement in comments. Then I changed the if to always be False and the error persisted when the line of code was not in comments, even though it could never reach that piece of code.
for (let i = 0; i < dayArray.length; i+=1) {
if (false) {
const resultThatIsNotNeeded = await dispatch(getStuff(dayArray[i])
}
// more business logic
}
Changing the for loop to a ForEach loop fixed this issue somehow. But I really have no clue why this fixed it.
dayArray.forEach(async (day, i) => {
if (false) {
const resultThatIsNotNeeded = await dispatch(getStuff(dayArray[i])
}
}
That is because on your forEach the await call is inside of a async function as it should be
On the for loop I don't see any of this code being executed within a async function

React Native Expo Task Manager

Eventually, I would like to be able to run background tasks in my React Native app (Axios fetch to get some fresh data at least once a day). I am struggling to make this work:
https://docs.expo.io/versions/latest/sdk/task-manager/
import * as BackgroundFetch from 'expo-background-fetch';
import * as TaskManager from 'expo-task-manager';
const FETCH_TASKNAME = 'test_task'
const INTERVAL = 60
function test() {
console.log('function is running')
}
export async function registerFetchTask() {
TaskManager.defineTask(FETCH_TASKNAME, test());
const status = await BackgroundFetch.getStatusAsync();
switch (status) {
case BackgroundFetch.Status.Restricted:
case BackgroundFetch.Status.Denied:
console.log("Background execution is disabled");
return;
default: {
console.debug("Background execution allowed");
let tasks = await TaskManager.getRegisteredTasksAsync();
if (tasks.find(f => f.taskName === FETCH_TASKNAME) == null) {
console.log("Registering task");
await BackgroundFetch.registerTaskAsync(FETCH_TASKNAME);
tasks = await TaskManager.getRegisteredTasksAsync();
console.debug("Registered tasks", tasks);
} else {
console.log(`Task ${FETCH_TASKNAME} already registered, skipping`);
}
console.log("Setting interval to", INTERVAL);
await BackgroundFetch.setMinimumIntervalAsync(INTERVAL);
}
}
}
and calling this in App.js
import { registerFetchTask } from './helpers/backgroundFetch'
registerFetchTask();
I am getting a console logs up to this point:
function is running
Background execution allowed
Registering task
But I am unfortunately also getting following errors:
TaskManager.defineTask must be called during the initialization phase!
I read also in the documentation and as per example code, I am running in App.js directly and not in the component class.
And I am getting the following warning:
[Unhandled promise rejection: Error: Task 'test_task' is not defined. You must define a task using TaskManager.defineTask before registering.]
Which I don't understand since it is defined at the very top and before registering.
It is only unfortunate there is no proper working example anywhere to be found. An example would save countless hours for people struggling with this. Is there maybe an easier way of making background tasks running in react native apps?
Thanks so much for your kind help.
I can spot a couple of problems:
When you define the task, pass in a reference to the function rather than calling it:
TaskManager.defineTask(FETCH_TASKNAME, test); // no parentheses
registerFetchTask() is async which means it returns a promise when called in App.js. That probably doesn't count as the "initialization phase" of the app so try removing async
I don't know whether these changes will solve the problem but they should help.
change the line TaskManager.defineTask(FETCH_TASKNAME, test()); to
TaskManager.defineTask(FETCH_TASKNAME, test);
instead of passing the return value of the function pass the function reference.

Aws Cognito Presignup trigger fails with InvalidLambdaResponseException

My pre-signup-trigger lambda fails with the InvalidLambdaResponseException. Using nodejs. The user registration works without the trigger.
I tried pretty much all solutions suggested on SO how to handle this trigger. I have tried ending the lambda with context.done(null, event) and callback(null, event). The test script works.
Worth mentioning that I have around 10 user attributes including 7 custom.
exports.handler = (event, context, callback) => {
// Check if business phone exists
event.response.autoConfirmEmail = false;
// This example uses a custom attribute "custom:domain"
if (event.request.userAttributes.hasOwnProperty("custom:business_phone")) {
if ( event.request.userAttributes["custom:business_phone"] !== null
&& event.request.userAttributes["custom:business_phone"] !== "") {
event.response.autoConfirmEmail = true;
}
}
// Return to Amazon Cognito
callback(null, event);
//context.done(null, event);
};
Test event works but user signup in browser returns InvalidLambdaResponseException. Tried one or both of the last two lines.
UPDATE: Getting same exception for Post confirm trigger. used aws doc example as is. Using runtime NodeJs 10.x. Tried 8.10 too.
To all he experts out there, please help!
I had the same problem and it turned out the error was caused by another lambda that I had in my cloudformation:
exports.handler = (event, context, callback) => {
if (event.triggerSource === "CustomMessage_ForgotPassword") {
event.response.emailSubject = "Reset your password for blah";
event.response.emailMessage = "Blah blah";
callback(null, event);
}
};
As signup sends an email, it was also executing the above lambda. But callback(null, event); was inside if statement and therefore not executed, since event.triggerSource was not "CustomMessage_ForgotPassword".
Fixing that by putting callback(null, event); outside of if statement solved the whole problem.
I'd suggest checking your other lambdas if they always execute callback(null, event) in the end, because error may be caused by a different lambda than you'd expect.

static method in react native bug(callback)

I will try my best to explain the problem i have.
here is a sample code
auth.js
static authenticate(email,password,callbackIsLogged)
{
//some logic
if(passwordCorrect)
{
callbackIsLogged(true);
}
else
{
callbackIsLogged(false);
}
}
login.js
loginButtonClicked()
{
Authcontroller.authenticate(email,password,function(loginState)
{
if(loginState)
{
alert('correect');
//proceed withlogin.
}
else
{
alert('error');
}
});
}
the problem i have is weired.
lets look at a sample scenario where this bug happens.
if i login with correct username and password for the first time when the app opens everything goes according to plan.
But if i enter the incorrect password at the first time and the second time enter the correct password the callback function will get called twice with boolean value true and false.
It seems like the static function somehow hold the previous callbacks and execute them.
hope you undestood my question. how to fix this.
thanks.