The fetch fonction load infinitely (Shopify) - javascript

I have try this but I wasn't able to add a cookie or locale storage condition so it won't reload infinitely.
fetch('https://get.geojs.io/v1/ip/country')
.then(response => response.text())
.then(country_code => {
var domain_and_tld = window.location.host.split('.').splice(-2).join('.');
country_code = country_code.trim().toLowerCase();
switch (country_code) {
case 'us':
window.location.host = domain_and_tld;
break;
case 'gb':
window.location.host = `${domain_and_tld}?currency=GBP`;
break;
case 'fr':
window.location.host = `${domain_and_tld}?currency=EUR`;
break;
};
})
.catch(err => console.error(err));
Thanks for your help :)

It seems you want to change the query params based on the users country. We don't need to change window.location.host. You can change query params using window.location.search.
However, you only want to change window.location.search if it does not match your desired value (to avoid reloading infinitely). The solution below assumes currency is the only query param in your URL.
fetch('https://get.geojs.io/v1/ip/country')
.then(response => response.text())
.then(country_code => {
const country_code = country_code.trim().toLowerCase();
let desiredSearchParams = '';
switch (country_code) {
case 'gb':
desiredSearchParams = `?currency=GBP`;
break;
case 'fr':
desiredSearchParams = `?currency=EUR`;
break;
case 'us':
default:
break;
};
if(desiredSearchParams !== window.location.search) {
//change search param only if desired search param different from current search param
window.location.search = desiredSearchParams;
}
})
.catch(err => console.error(err));

Related

Using object literals for my complex cases

Hey I was wondering if it is somehow possible to use a object literal in this case to clean up my switch statement.
export const getTravelInfo = () => {
const url = window.location.href;
switch (url as any) {
case url.includes('trips'):
return epicTrips;
case url.includes('mini-trips'):
return miniTrips;
case url.includes('sailing-trips'):
return sailingTrips;
default:
return epicTrips;
}
};
This is what I have so far, I am just not sure how or even if this is possible to pass in a function and loop over the url to determine what string is present in the url and then deliver that value to the user.
function getTravelInfo2 () {
const url = window.location.href;
var travel = {
'trips': epicTrips,
'mini-trips': miniTrips,
'sailing-trips': sailingTrips,
'default': epicTrips
};
return travel[url];
}
My solution was to First get what I need from the URL Via
const url = 'http://www.test.com/trips';
firstPart = url.split('/', -1)[-1];
getTravelInfo(firstPart);
const getTravelInfo = (type) => {
var travel = {
'trips': epicTrips,
'mini-trips': miniTrips,
'sailing-trips': sailingTrips,
'default': epicTrips
};
return (travel[type] || travel['default']);
}
Much cleaner and easier to execute and understand.

Refactor this function to reduce its Cognitive Complexity from 18 to the 15 allowed

On Sonarqube I'm getting this as critical issue, can somebody help me in this to sort out this issue.
Here is the code details, please let me know how can I refactor this code with switch case :
const getEmailTo = (subject) => {
switch (subject) {
case 'POWERUP_REWARDS':
return COMMON_EMAIL;
case 'GAME_INFORMER':
return COMMON_EMAIL;
case 'ONLINE_ORDER':
return 'test#gmail.com';
case 'STORE_EXPERIENCE':
return 'test#gmail.com';
case 'APP_REVIEW':
return COMMON_EMAIL;
case 'SOMETHING_ELSE':
return COMMON_EMAIL;
default:
return '';
}
};
Make your code a bit more DRY and simplified by collecting your common cases that return the same values. I don't think SonarQube validates readability, but proper use of whitespace can go a long way in readability of unfamiliar code. It's opinionated, but I like a line between case returns.
const getEmailTo = (subject) => {
switch (subject) {
case 'POWERUP_REWARDS':
case 'GAME_INFORMER':
case 'APP_REVIEW':
case 'SOMETHING_ELSE':
return COMMON_EMAIL;
case 'ONLINE_ORDER':
case 'STORE_EXPERIENCE':
return 'test#gmail.com';
default:
return '';
}
};
You can use an object to map subjects to email addresses and return the email address corresponding to the subject.
const TEST_EMAIL = 'test#gmail.com'
const emails = {
POWERUP_REWARDS: COMMON_EMAIL,
GAME_INFORMER: COMMON_EMAIL,
APP_REVIEW: COMMON_EMAIL,
SOMETHING_ELSE: COMMON_EMAIL,
ONLINE_ORDER: TEST_EMAIL,
STORE_EXPERIENCE: TEST_EMAIL,
}
const getEmailTo = (subject) => emails[subject] || ''
I'm not sure if returning '' is fine when a subject is not in the mapping. I would suggest throwing an error to let the caller know the subject is invalid.
const getEmailTo = (subject) => {
if (!(subject in emails)) {
throw new Error(`Invalid subject: ${subject}`)
}
return emails[subject]
}
You can just put the related case statements next to each other, like this:
const getEmailTo = (subject) => {
switch (subject) {
case 'POWERUP_REWARDS':
case 'GAME_INFORMER':
case 'APP_REVIEW':
case 'SOMETHING_ELSE':
return COMMON_EMAIL;
case 'ONLINE_ORDER':
case 'STORE_EXPERIENCE':
return 'test#gmail.com';
default:
return '';
}
};

Render component when props changed, otherwise not shown

I have this Output component which should be rendered when it get props from the parent component.
How can I do this?
Right now, it renders when I click a button but without the getTranslate function getting called. In debugger I can see that the component has the props needed, it just doesn't run my getTranslate function
import React, { useState } from "react";
import Axios from "axios";
const Output = (props) => {
const [output, setOutput] = useState(null);
const [url, setUrl] = useState(null);
const getUrl = (language, text) => {
console.log("GetURL ran with: ", language, text);
let url = "";
switch (language) {
case "yoda":
url =
" https://api.funtranslations.com/translate/yoda.json?text=" + text;
break;
case "valyrian":
url =
"https://api.funtranslations.com/translate/valyrian.json?text=" +
text;
break;
case "sith":
url =
"https://api.funtranslations.com/translate/sith.json?text=" + text;
break;
case "shakespeare":
url =
"https://api.funtranslations.com/translate/shakespeare.json?text=" +
text;
break;
case "pirate":
url =
"https://api.funtranslations.com/translate/pirate.json?text=" + text;
break;
case "minion":
url =
"https://api.funtranslations.com/translate/minion.json?text=" + text;
break;
case "lolcat":
url =
"https://api.funtranslations.com/translate/lolcat.json?text=" + text;
break;
case "klingon":
url =
"https://api.funtranslations.com/translate/klingon.json?text=" + text;
break;
case "hacker":
url =
"https://api.funtranslations.com/translate/hacker.json?text=" + text;
break;
case "dothraki":
url =
"https://api.funtranslations.com/translate/dothraki.json?text=" +
text;
break;
default:
break;
}
setUrl(url);
};
const getTranslate = () => {
getUrl(props.language, props.text);
const axios = require("axios");
axios.get(function (respone) {
console.log("Here comes response from api call: ", respone);
return respone.contents.translated;
});
};
return (
<div>
<textarea placeholder="Translated..." value={{ getTranslate }}></textarea>
</div>
);
};
export default Output;
The probable problem is you are not calling getTranslate function, looks like it should be getTranslate(); also you need to update state once you receive data.. see I have placed comments to guide to towards a solution... getTranslate is not returning any value, and the place you are calling it not appropriate...
const getTranslate = () => {
getUrl(props.language, props.text);
const axios = require("axios");
axios.get(function (respone) {
console.log("Here comes response from api call: ", respone);
/// update the variable /state/ prop that you want to bind
return respone.contents.translated;
});
};
Then bind the value in template:
return (
<div>
<textarea placeholder="Translated..." value={ the value to bind from state/prop}></textarea>
</div>
)
;
To call getTranslate(), you can use hooks lifecycle method useEffect(). And value returned from this function can be set to some state and bind the set state to text area value.
import React, { useState, useEffect } from "react";
import Axios from "axios";
const Output = (props) => {
const [output, setOutput] = useState('');
const [url, setUrl] = useState('');
useEffect(()=>{
getTranslate();
})
const getUrl = (language, text) => {
console.log("GetURL ran with: ", language, text);
let url = "";
switch (language) {
case "yoda":
url =
" https://api.funtranslations.com/translate/yoda.json?text=" + text;
break;
case "valyrian":
url =
"https://api.funtranslations.com/translate/valyrian.json?text=" +
text;
break;
case "sith":
url =
"https://api.funtranslations.com/translate/sith.json?text=" + text;
break;
case "shakespeare":
url =
"https://api.funtranslations.com/translate/shakespeare.json?text=" +
text;
break;
case "pirate":
url =
"https://api.funtranslations.com/translate/pirate.json?text=" + text;
break;
case "minion":
url =
"https://api.funtranslations.com/translate/minion.json?text=" + text;
break;
case "lolcat":
url =
"https://api.funtranslations.com/translate/lolcat.json?text=" + text;
break;
case "klingon":
url =
"https://api.funtranslations.com/translate/klingon.json?text=" + text;
break;
case "hacker":
url =
"https://api.funtranslations.com/translate/hacker.json?text=" + text;
break;
case "dothraki":
url =
"https://api.funtranslations.com/translate/dothraki.json?text=" +
text;
break;
default:
break;
}
setUrl(url);
};
const getTranslate = () => {
console.log("From get translate")
getUrl(props.language, props.text);
Axios.get(function (respone) {
console.log("Here comes response from api call: ", respone);
setOutput(respone.contents.translated);
});
};
return (
<div>
<textarea placeholder="Translated..." value={output} onChange={()=>console.log("Testing")}></textarea>
</div>
);
};
export default Output;
You need to move your translate functionality to either the "onChange" function or the "onBlur" function (if you want the text to be translated after the user clicks out).
Also the functions you pass to onChange and onBlur should manage the async nature of your translate functionality.
You can use a useEffect Method which will run every time when props changes or component renders.
useEffect(()=>{
getTranslate();
}, [props])

Dynamically create a links from an array of items

I need to create a ul of links based on the valued in an array. The links are created but the href attribute is being randomly assigned and doesn't correspond to the actual value I'm passing in to my getUrl function.
Here is my code so far:
getURL (type) {
let url
switch (type) {
case 'Yahoo':
url = 'https://www.yahoo.com/'
case 'Bing':
url = 'https://www.bing.com/'
default:
url = 'https://www.google.com'
}
return url
}
and the render:
render () {
let { expandList } = this.state
let listItems = [
'Google',
'Bing',
'Yahoo'
]
let list = expandList
? listItems.map((item, index) => {
return (
<li key={index}>
<a href={this.getURL(item)} target='_blank'>
{item}
</a>
</li>
)
})
: ''
return (
<div>
<ul>{list}</ul>
</div>
)
}
You need to break after each case or return from it. If you don't it will always continue to default, and return the google url.
function getURL(type) {
switch (type) {
case 'Yahoo':
return 'https://www.yahoo.com/'
case 'Bing':
return 'https://www.bing.com/'
default:
return 'https://www.google.com'
}
}
console.log(getURL('Yahoo'));
console.log(getURL('Bing'));
switch basically tries to match type with the argument to the case, and when there's a match, it will execute the codes in all the cases below it unless you explicitly break it.
default is a catch-all in case none of the cases match the type.
The correct way to do it with switch would be breaking out of it after the case statement is executed. One way of doing this is by inserting break:
getURL (type) {
let url
switch (type) {
case 'Yahoo':
url = 'https://www.yahoo.com/'
break
case 'Bing':
url = 'https://www.bing.com/'
break
default:
url = 'https://www.google.com'
}
return url
}
You can also definitely return the url in the case statement as Ori Drori suggested, which will not only break out of the switch, but also break out of the function.
I would also recommend ending your statements with a semicolon. Even though it's optional, it can prevent unexpected errors.
Also, I would recommend lowercasing type with type.tolowercase() and match it with lowercase strings.
If all getURL does is to map the name of the website to the url, an alternative with less code would be using an object:
var nameToUrlMap = {
'yahoo': 'https://www.yahoo.com/',
'bing': 'https://www.bing.com/',
};
and then use it like:
var type = 'Yahoo';
var lowercasedType = type.tolowercase();
var url = nameToUrlMap[lowercasedType] || 'https://www.google.com/'; // falls back to google if name doesn't exist in nameToUrlMap
console.log(url); // "https://www.yahoo.com/"
console.log(nameToUrlMap['abcd'] || 'https://www.google.com/'); // "https://www.yahoo.com/"
You can wrap it in a function if you want:
var nameToUrlMap = {
'yahoo': 'https://www.yahoo.com/',
'bing': 'https://www.bing.com/',
};
function getURL(type) {
var lowercasedType = type.tolowercase();
var url = nameToUrlMap[lowercasedType] || 'https://www.google.com/'; // falls back to google if name doesn't exist in nameToUrlMap
}
You can use const or let in place of var as well.

node_redis client - Cannot return out values from a query

I'm going crazy with a problem which I can not find solution. I can not return out values from a redis query. I am using node_redis client (http://redis.js.org/) as redis driver for Node.JS.
The problem is: I wrote a function for get the user status connection and return it for take the value from other function.
//CHECK USER STATUS
exports.checkUserStatus = function(uid){
redis.multi()
.sismember('users:online',uid)
.sismember('users:iddle', uid)
.sismember('users:out', uid)
.sismember('users:locked', uid)
.exec(function(err, res){
res.forEach(function(res, index){
if(res != 0){
switch(index){
case 0:
return 'online';
break;
case 1:
return 'iddle';
break;
case 2:
return 'out';
break;
case 3:
return 'locked';
break;
default:
return 'offline';
}
}
});
})
}
But function return nothing!. If I replace the return line with a console.log(), it work! but I don't need a console.log(), I need take the value.
I tried too create a variable outside of the query and set it from inside and then return it but, it doesn't work.
Somebody know how may I do that?
Thank you!
I'm not a redis expert but ... maybe you simply missing the return keyword?
var result;
exports.checkUserStatus = function(uid){
redis.multi()
...
.exec(function(err, res){
res.forEach(function(res, index){
if(res != 0){
switch(index){
case 0:
result = 'online';
break;
case 1:
result ='iddle';
break;
case 2:
result = 'out';
break;
case 3:
result = 'locked';
break;
default:
result = 'offline';
}
}
});
})
return result;
}
Based on manual from http://redis.io/commands/MULTI multi returns value, which you doesn't return.
In this site but, in spanish I received the right answer. I post here for help to others:
//CHECK USER STATUS ... Take a look at the new parameter 'callback' in the function!
exports.checkUserStatus = function(uid, callback){
redis.multi()
.sismember('users:online',uid)
.sismember('users:iddle', uid)
.sismember('users:out', uid)
.sismember('users:locked', uid)
.exec(function(err, res){
res.forEach(function(res, index){
if(res != 0){
switch(index){
case 0:
// Here invoke the user's function
// and I pass the info
callback('online');
break;
case 1:
callback('online');
break;
case 2:
callback('online');
break;
case 3:
callback('locked');
break;
default:
callback('offline');
}
}
});
})
}
And then I catch the returned value as you will see below:
// sequence of events
// This happend first - #1
checkUserStatus('uid-12343', function(status, user) {
// This happend at the end - #2
// Here we catch the status in asynchronous way
});
// This happend second - #2
console.log("This happend before the redis info arrive!");
Thank you to everyone! I hope I've helped!

Categories