need return after navigation.goback()? - react-navigation

With React Navigation 5.x, shall return be used after navigation.goBack() in the code snippet below?
if (condition_met) {
setTimeout(()=> {
navigation.goBack();
return; //<<==needed after navigation or useless/never executed?
}, 1000);
}
//do something else if above condition not met.

The function called by setTimeout is executed after // do something else.
Move the return statement outside of setTimeout
if (condition_met) {
setTimeout(()=> {
navigation.goBack();
}, 1000);
return; //condition met stop executing code further
}
//do something else if above condition not met.

It is normally advised to handle such effects in the return function of a useEffect as that is called when a component is being closed.
useEffect(() => {
return () => {
// cleanup code codes here
};
},[]);
This will work after the navigation.goBack() closes the screen component.

Related

Cypress : XPATH - Do something if the element exists

I need to click on a button if the button exists. I am using the cypress xpath. Currently i am using below code but not working
cy.xpath('//button[text()="New"]')
.then(($button) => {
if ($button.is(':visible')) {
cy.log('visible')
cy.xpath('//button[text()="New"]').click();
} else {
//do something
}
})
In case if you want to click a button based on it existence, you can do like this:
cy.get('body').then(($body) => {
if ($body.find('button:contains("New")').length > 0) {
cy.log('visible')
cy.xpath('//button[text()="New"]').click()
} else {
//do something
}
})
In case if you want to check if the element is visible and then click on it.
cy.xpath('//button[text()="New"]').then(($button) => {
if ($button.is(':visible')) {
cy.log('visible')
cy.wrap($button).click()
} else {
//do something
}
})
XPath has a count() function that tells you if the element exists.
cy.xpath('count(//button[text()="New"])').then(count => { // check existence first
if (count) {
cy.xpath('//button[text()="New"]').then($button =>
if ($button.is(':visible')) {
cy.log('visible')
cy.wrap($button).click()
} else {
//do something
}
}
})
Splitting exists and visible checks like that will work if the DOM is stable.

RxJs wrap function in Observable

I have a question how do you wrap a normal sync code inside observable. Let's take this example:
let isCalling = false;
function makeHttpCall(url) {
isCalling = true;
return rxJsFetch(url).pipe(tap(() => (isCalling = false)));
}
Problem with that function is that isCalling flag will be set no matter if someone subscribes or not. I don't want that (becuase it is not calling yet). To combat that I usually do something like:
let isCalling = false;
function makeHttpCallWrapped(url) {
return of(null).pipe(
mergeMap(() => {
isCalling = true;
return rxJsFetch(url).pipe(tap(() => (isCalling = false)));
}),
);
}
And that works, isCalling is set only after subscribe.
Problem with that code is that it is not very elegant, nor clear to someone starting with RxJs. My question to you is, how do you handle that? Is there something in RxJs that I don't know about that handles it more gracefully?
RxJS Defer Operator
Defer lets you create an observable upon subscription. It's exactly a cleaner version of what you're already doing.
let isCalling = false;
function makeHttpCall(url) {
return defer(() => {
isCalling = true;
return rxJsFetch(url).pipe(tap(() => (isCalling = false)));
});
}
To make it more graceful I create a helper method fromFunction:
import { of } from 'rxjs';
import { mergeMap } from 'rxjs/operators';
import { SubscribableOrPromise } from 'rxjs/src/internal/types';
export function fromFunction<T>(func: () => SubscribableOrPromise<T>) {
return of(undefined).pipe(mergeMap(func));
}
And then use it like:
let isCalling = false;
function makeHttpCallWrapped(url) {
return fromFunction(() => {
isCalling = true;
return rxJsFetch(url).pipe(tap(() => (isCalling = false)));
});
}
I kind of feel like from should also accept input like that.

Axios handle error using interceptor (js promises)

I am using an interceptor in axios to check for errors.
service.interceptors.response.use(
response => response,
error => {
const originalRequest = error.config
if (!error.response) {
// No network connectivity
}
}
)
My request looks like this
service.post('endpoint').then(response => {
// Successful request
}).catch(error => {
// Handle error
})
In case there is any error such as an unsuccessful status code (e. g. 400), I wan't to handle the error in the catch part of the second code example. However, if there is a network issue, I wan't to handle the error in the first code example. In that case neither then, nor catch of the second code example should be called. How can I achieve this?
When you have a promise chain already in place you can't stop the flow:
const axios = require('axios')
axios.interceptors.response.use(
response => response,
manageErrorConnection
)
// here you have created a promise chain that can't be changed:
axios.get('http://localhost:3000/user?ID=12345')
.then(handleResponse)
.catch(handleError)
function manageErrorConnection(err) {
if (err.response && err.response.status >= 400 && err.response.status <= 500) {
// this will trigger the `handleError` function in the promise chain
return Promise.reject(new Error('Bad status code'))
} else if (err.code === 'ECONNREFUSED') {
// this will trigger the `handlerResponse` function in the promise chain
// bacause we are not returning a rejection! Just an example
return 'nevermind'
} else {
// this will trigger the `handleError` function in the promise chain
return Promise.reject(err)
}
}
function handleResponse(response) {
console.log(`handleResponse: ${response}`);
}
function handleError(error) {
console.log(`handleError: ${error}`);
}
So in order to run an optional step, you need to:
put logic in the handler, to skip it
put the handler in the chain when it is needed (I would just avoid that since it is "spaghetti software")
put the logic in the handler example
// .... changing this line ...
return Promise.reject('nevermind')
// ....
function handleError(error) {
if (error === 'nevermind') {
return
}
console.log(`handleError: ${error}`);
}
This logic could be isolated:
axios.get('http://google.it/user?ID=12345')
.then(handleResponse)
.catch(shouldHandleError)
.catch(handleError)
function manageErrorConnection(err) { return Promise.reject('nevermind') }
function handleResponse(response) { console.log(`handleResponse: ${response}`); }
function shouldHandleError(error) {
if (error === 'nevermind') {
// this stop the chain
console.log('avoid handling');
return
}
return Promise.reject(error)
}
function handleError(error) { console.log(`handleError: ${error}`); }

How to fail all tests within "describe" block if first test fail in protractor/jasmine?

I would like to fail whole describe block if first test fail within it?
Is this possible with protractor/jasmine?
You can most probably just use the Jasmine built-in done.fail possibility.
Read about it here
As an example in your question is missing, here the plain example from jasmines introduction page:
describe("A spec using done.fail", function() {
var foo = function(x, callBack1, callBack2) {
if (x) {
setTimeout(callBack1, 0);
} else {
setTimeout(callBack2, 0);
}
};
it("should not call the second callBack", function(done) {
foo(true,
done,
function() {
done.fail("Second callback has been called");
}
);
});
});

react-redux action to reducer relationship

So I am learning React-Redux. I am trying to find a way to load a value from the database first on load instead of just starting from 0. I have written an action that will hit an endpoint on my node file and pull from my mongo database. This works. However the action never seems to reach the reducer to actually update the store. Can someone explain to me the right way to make sure this action is store aware.
Here is the code for the action. Note the console.log with the number prints out what I want. I just never see the logs in the reducer that it was even ever reached.
export function setFooClicks(){
console.log("in the set foo clicks action")
var number = 0;
//return function(dispatch){
//console.log("in the return function")
return axios.get('/clicks').then(result => {
number = result.data
console.log("The number of clicks is", number)
//return number
return{
type: types.SETFOOCLICKS,
totalFoo: result.data
}
}).catch((error) => {
return console.log(error);
})
//}
}
I am trying to grab it in the top level container at the moment so here is the code for that.
import React, { Component } from 'react'
import { connect } from 'react-redux'
import Foo from '../components/Foo'
import { incrementFoo, setFooClicks } from '../actions'
class FooContainer extends Component {
componentDidMount(){
setFooClicks();
}
render() {
return (
<div>
<Foo incrementFooAction={() => this.props.incrementFoo()} totalFoo={this.props.totalFoo}/>
</div>
)
}
}
function mapStateToProps(state) {
return {
totalFoo: state.foo.totalFoo
}
}
export default connect(mapStateToProps, { incrementFoo,setFooClicks })(FooContainer)
The normal incrementFoo action works but trying to add the setFooClicks action into the component as well doesn't. Lastly here is the code to the reducer funciton. All I did was add a case to the switch block.
export default function incrementFoo(state = initialState, action) {
console.log("I am in the foo reducer")
console.log(action.type)
switch (action.type) {
case INCREMENT:
console.log(state.totalFoo);
return {
...state,
totalFoo: state.totalFoo + 1
}
case SETFOOCLICKS:
console.log("in the SETFOOCLICKS reducer")
return{
...state,
totalFoo: action.totalFoo
}
default:
return state
}
}

Resources