const scoping issue within a switch statement - javascript

I have the following code in my reducer. In both cases, findFile() returns a result, however, only in the first occurrence (setImageRotation) will "origFile" get set. Changing the name of the second occurrence of "origFile" will allow it to get set. I'm wondering why this is case, as const has a block level scope.
function handler(stateArg, action) {
const state = stateArg || {};
let nextState;
switch (action.type) {
case actions.types.setImageRotation: {
const origFile = findFile(action.fileUid, state.files);
const newfile = Object.assign({}, origFile, { rotation: action.rotation });
nextState = updateStateFile(state, newfile);
break;
}
case actions.types.setImageRegionOfInterest: {
const origFile = findFile(action.fileUid, state.files);
const newfile = Object.assign({}, origFile, { roi: action.roi });
nextState = updateStateFile(state, newfile);
break;
}
}
return nextState || state;
}
Notes:
origFile is not defined anywhere else in my solution.
there are no console errors
Transpiled Code:
case actions.types.setImageRegionOfInterest:{
var origFile = findFile(action.fileUid, state.files);
var newfile = (0, _assign2.default)({}, origFile, { roi: action.roi });
nextState = updateStateFile(state, newfile);
break;
}
case actions.types.setImageRotation:{
var _origFile = findFile(action.fileUid, state.files);
var _newfile = (0, _assign2.default)({}, _origFile, { rotation: action.rotation });
nextState = updateStateFile(state, _newfile);
break;
}

As people stated in the discussion, this code works. What I ran into was a bug with Google Chromes debugger & source mapping. When I turned source mapping off and debugged the transpiled code, I got the correct value for "origfile".

Related

Using switch case in javascript

This is the variable i am having right now
[
{
"_id":"63773059c3160f782c087e33",
"nfrid":"637328ebf5c4b2558b064809",
"nfrname":"azuread",
"fileName":"package.json",
"isImport":false,
"isConst":false,
"isComponent":false,
"isNewFile":false,
"landmark":"\"react\"",
"isAfter":false,
"fileContent":"\"#azure/msal-react\": \"^1.4.9\",",
"filePath":"package.json",
"isPackage":true,
"isIndexHtml":false,
"projecttypeid":"6372366d1b568e00d8af2e44",
"projecttypetitle":"PWA React",
"nfrGitIo":[
{
"_id":"637328ebf5c4b2558b064809",
"iconpath":"https://cdnerapidxdevportal.azureedge.net/webdesignerimages/azure-active-directory-aad-icon-488x512-3d71nrtk.png",
"title":"Azure AD",
"description":"Azure Active Directory (Azure AD), part of Microsoft Entra, is an enterprise identity service that provides single sign-on, multifactor authentication, and conditional access to guard against 99.9 percent of cybersecurity attacks."
}
]
},
{
"_id":"63773144c3160f782c087e35",
"nfrid":"637328ebf5c4b2558b064809",
"nfrname":"azuread",
"fileName":"index.js",
"isImport":true,
"isConst":false,
"isComponent":false,
"isNewFile":false,
"isPackage":false,
"landmark":null,
"isAfter":null,
"fileContent":"import { MsalProvider } from '#azure/msal-react';import { msalConfig } from './authConfig';import {PublicClientApplication } from '#azure/msal-browser';",
"filePath":"src/index.js",
"isIndexHtml":false,
"projecttypeid":"6372366d1b568e00d8af2e44",
"projecttypetitle":"PWA React",
"nfrGitIo":[
{
"_id":"637328ebf5c4b2558b064809",
"iconpath":"https://cdnerapidxdevportal.azureedge.net/webdesignerimages/azure-active-directory-aad-icon-488x512-3d71nrtk.png",
"title":"Azure AD",
"description":"Azure Active Directory (Azure AD), part of Microsoft Entra, is an enterprise identity service that provides single sign-on, multifactor authentication, and conditional access to guard against 99.9 percent of cybersecurity attacks."
}
]
},
]
I am having many flags like isImport, isPackage, isIndexHtml like that. I am trying to put those flags in a switch case and call individual function when each flag is true.Something like this,
for (let i = 0; i < cosmos.length; i++) {
console.log(cosmos[0].isPackage);
switch (cosmos[i]) {
case `${cosmos[i].isImport === true}`:
const statusImport = common.updateImport(cosmos[i]);
console.log(statusImport);
break;
// case `${cosmos[i].isConst === true}`:
// console.log("I own a dog");
// break;
case `${cosmos[i].isPackage === true}`:
const statusPackage = common.updatePackage(cosmos[i]);
console.log(statusPackage);
break;
case `${cosmos[i].isIndexHtml === true}`:
const statusIndexHtml = common.updateIndexHTML(cosmos[i]);
console.log(statusIndexHtml);
break;
// case `${cosmos[i].isNewFile === true}`:
// const statusNewFile = common.addNewFile(cosmos[i]);
// console.log(statusNewFile);
// break;
default:
console.log("Nothing to add/update");
break;
}
}
But when I run this i am always getting the default console log. I dont know what i am missing
This is my first switch case implementation. Can someone point me in the right direction?
Don't convert them to strings and in switch condition add just true:
for (let i = 0; i < cosmos.length; i++) {
console.log(cosmos[0].isPackage);
switch (true) {
case cosmos[i].isImport:
const statusImport = common.updateImport(cosmos[i]);
console.log(statusImport);
break;
case cosmos[i].isPackage:
const statusPackage = common.updatePackage(cosmos[i]);
console.log(statusPackage);
break;
case cosmos[i].isIndexHtml:
const statusIndexHtml = common.updateIndexHTML(cosmos[i]);
console.log(statusIndexHtml);
break;
default:
console.log("Nothing to add/update");
break;
}
}
switch is not the right construct to use in this case.
Simply use if/else here.
Since you're testing several different values from cosmos[i], not testing a single value against multiple possible matches, switch isn't the right tool here. (You can use it, just like you can use a wrench to bang in a nail, but it's not the right tool.) Instead, use an if/else if/else chain:
for (let i = 0; i < cosmos.length; i++) {
if (cosmos[i].isImport) {
const statusImport = common.updateImport(cosmos[i]);
console.log(statusImport);
} else if (cosmos[i].isPackage) {
const statusPackage = common.updatePackage(cosmos[i]);
console.log(statusPackage);
} else if (cosmos[i].isIndexHtml) {
const statusIndexHtml = common.updateIndexHTML(cosmos[i]);
console.log(statusIndexHtml);
} else {
console.log("Nothing to add/update");
}
}
Separately, in new code, I'd suggest using a for-of instead of a for when you don't need the index:
for (const entry of cosmos) {
if (entry.isImport) {
const statusImport = common.updateImport(entry);
console.log(statusImport);
} else if (entry.isPackage) {
const statusPackage = common.updatePackage(entry);
console.log(statusPackage);
} else if (entry.isIndexHtml) {
const statusIndexHtml = common.updateIndexHTML(entry);
console.log(statusIndexHtml);
} else {
console.log("Nothing to add/update");
}
}
A switch statement can only interrogate one variable. In your case the correct solution is an if statement for each member variable. Replace the switch statement with this snippet:
if (cosmos[i].isImport === true) {
const statusImport = common.updateImport(cosmos[i]);
console.log(statusImport);
}
if (cosmos[i].isPackage === true) {
const statusPackage = common.updatePackage(cosmos[i]);
console.log(statusPackage);
}
if (cosmos[i].isIndexHtml === true) {
const statusIndexHtml = common.updateIndexHTML(cosmos[i]);
console.log(statusIndexHtml);
}
I note that your data structure does not mutually exclude the isImport isPackage and isIndexHtml - so in principle any combination of them could be true and my proposed code would execute accordingly.

traverse array of objects and show image according to a type

I have an array of objects in a state in pinia, I get this array in my component. I am trying to show an image or others according to a value that is in the object, I make a function where I go through the array here and using switch I check the type, and return the image that corresponds to the type, I do this but I only get returns the first image if I use a for, if I do it with forEach it returns null, I try to save the value in the function because it is the one that I command to call to show the image, how can I do this so that according to a type I show a different image?
Function where you tried to get the images
const imgSelect = () => {
for(let i = 0; i < obj.value.length; i++){
switch(obj.value[i].type){
case 'one':
return new URL('../assets/images/image1.png', import.meta.url).href
break;
case 'two':
return new URL('../assets/images/image2.png', import.meta.url).href
break;
case 'three':
return new URL('../assets/images/image3.png', import.meta.url).href
break;
default:
return null
break;
}
}
}
here I try to use the image, it is to show it on a map as a markup and show one image or another depending on the type
const imageMarker = imgSelect
As commented
You will have to use Array.map
You are only getting 1 image because you are using a return in for loop. So you return on 1st iteration and remaining iterations never gets evaluated
Sample:
const getUrl = (type) => {
switch (type) {
case 'one':
return new URL('../assets/images/image1.png',
import.meta.url).href
break;
case 'two':
return new URL('../assets/images/image2.png',
import.meta.url).href
break;
case 'three':
return new URL('../assets/images/image3.png',
import.meta.url).href
break;
default:
return null
break;
}
}
const imgSelect = () => {
obj.value = obj.value.map(
(item) => ({...item, url: getUrl(item.type)})
)
}
If you have predefined list of images based on type, you can even create a predefined map and fetch from that. No need to create for every iteration.
const URL_TYPE_MAP = {
one: new URL('../assets/images/image1.png', import.meta.url).href,
two: new URL('../assets/images/image2.png', import.meta.url).href,
three: new URL('../assets/images/image3.png', import.meta.url).href,
}
const getUrl = (type) => {
return URL_TYPE_MAP[type]
}

Better way of searching specific keywords in strings in JavaScript

I am working with an array of urls and for each url i wanna find a image corresponding to the site domain. my first attempt was
const url = new URL(props.url);
const platform = url.hostname.split(".")[1];
console.log(platform)
const platform_logos = {
"codechef": "images/chef.png",
"withgoogle": "images/google.png",
.
.
.
"codeforces": "images/codeforces.png",
}
let platform_logo = platform_logos[platform];
but it doesnt work with url of type 'https://momo2022fr.hackerearth.com' so i had to resort to
let platform_logo = "images/code.png"
if (url.includes("hackerearth")) {
platform_logo = "images/hackerearth.png"
}
else if (url.includes("hackerrank")) {
platform_logo = "images/hackerrank.png"
}
else if (url.includes("codeforces")) {
platform_logo = "images/codeforces.png"
}
else if (url.includes("codechef")) {
platform_logo = "images/chef.png"
}
else if (url.includes("atcoder")) {
platform_logo = "images/atcoder.png"
}
else if (url.includes("leetcode")) {
platform_logo = "images/leetcode.png"
}
else if (props.url.includes("withgoogle")) {
platform_logo = "images/google.png"
}
Is there any better way of writing the code below, it just feels like it violates DRY
You could change how you're reading the url to only get the root domain.
location.hostname.split('.').reverse().splice(0,2).reverse().join('.').split('.')[0]
This code would give hackerearth for https://momo2022fr.hackerearth.com/.
So there are several ways of achieving this.
These are just two from the top of my head.
Parsing the url and using a switch() to determine the outcome, with fallback if none is found.
const url = new URL("https://www.withgoogle.com/search?q=test");
const sites = [
"hackerearth",
"hackerrank",
"codeforces",
"codechef",
"atcoder",
"leetcode",
"withgoogle",
];
console.info(url.hostname);
const site = url.hostname.match(new RegExp(`${sites.join("|")}`));
let logo = "";
switch (site[0]) {
case "hackerearth":
logo = "images/hackerearth.png";
break;
case "hackerrank":
logo = "images/hackerrank.png";
break;
case "codeforces":
logo = "images/codeforces.png";
break;
case "codechef":
logo = "images/chef.png";
break;
case "atcoder":
logo = "images/atcoder.png";
break;
case "leetcode":
logo = "images/leetcode.png";
break;
case "withgoogle":
logo = "images/google.png";
break;
default:
logo = "images/code.png";
break;
}
console.info(logo);
Then there is the modern way, with less code and programming the fallback.
// const url = new URL("https://eee.com/test");
const url = new URL("https://www.withgoogle.com/search?q=test");
const sites = {
hackerearth: "images/hackerearth.png",
hackerrank: "images/hackerrank.png",
codeforces: "images/codeforces.png",
codechef: "images/chef.png",
atcoder: "images/atcoder.png",
leetcode: "images/leetcode.png",
withgoogle: "images/google.png",
default: "images/code.png",
};
let site = url.hostname.match(new RegExp(`${Object.keys(sites).join("|")}`));
if (site === null) {
site = "default";
}
console.info(site, sites[site]);
You could just do the same thing as in your first solution and store the mapping from the substring to the image path in an ocject:
const platform_logos = {
"hackerearth": "images/hackerearth.png",
"hackerrank": "images/hackerrank.png",
"codeforces": "images/codeforces.png",
"codechef": "images/chef.png",
"atcoder": "images/atcoder.png",
"leetcode": "images/leetcode.png",
"withgoogle": "images/google.png"
};
Then you could iterate over the key-value pairs in your object to find the key that is part of the URL and return it once it matches:
function getLogo(url) {
for(const [key, value] of Object.entries(platform_logos)) {
if(url.contains(key)) {
return value;
}
}
}
let platform_logo = getLogo(url);
You can iterate over the images and check URL:
const url = "https://example.com/codechef/asdasd/...";
const platform_logos = {
"codechef": "images/chef.png",
"withgoogle": "images/google.png",
"codeforces": "images/codeforces.png",
}
let img = "default.png";
for (const [key, value] of Object.entries(platform_logos)) {
if (url.includes(key)) {
img = value;
break;
}
}
console.log(img);

How to match a template string in switch statement with js?

I have a function that returns a component that depends on the pathname of the window.
getComponentByPathname = (pathname) => {
switch(patname){
case "/view1": return <ViewOneComponent>;
case "/view2": return <ViewTwoComponent>;
}
But the problem starts when I try to evaluate a template string that has one id
getComponentByPathname = (pathname) => {
switch(pathname){
case "/view1": return <ViewOneComponent>;
case "/view2": return <ViewTwoComponent>;
case `/view3/${getId()}`: return <ViewThreeComponent>;
}
It's only working with the first two cases. Why?
Also, I make another attempt. In this case, I literally paste the string with the Id in the third case, like this:
case "view3/1234567": return <ViewThreeComponent>;
And works. But the problem is that I can not hardcode the id in the string.
How I can evaluate that?
My guess would be that getId() is returning a different value then what you expect. I would try the following and make that getId() is returning the expected value when it is being calculated
getComponentByPathname = pathname => {
const case3 = `/view3/${getId()}`;
console.log(`case3 = ${case3}`);
console.log(`pathname = ${pathname}`);
switch (pathname) {
case '/view1':
return <ViewOneComponent>;
case '/view2':
return <ViewTwoComponent>;
case case3:
return <ViewThreeComponent>;
}
};
But if you only need to decide which component to render based on your path then something like this might be more appropriate
const examplePaths = ['view1/', 'view2/', 'view3/', 'view3/1241232', 'view3/8721873216', 'view4/', 'vi/ew1', ''];
const mapper = {
view1: 'ViewOneComponent',
view2: 'ViewTwoComponent',
view3: 'ViewThreeComponent'
};
examplePaths.forEach(ent => {
const splitPaths = ent.split('/');
const mapped = mapper[splitPaths[0]];
if (mapped) {
console.log(mapped);
} else {
console.log('Path not supported');
}
});
Works fine here
function getId() {
return 1234567
}
function test(pathname) {
switch (pathname) {
case '/view1':
return 'ViewOneComponent'
case '/view2':
return 'ViewTwoComponent'
case `/view3/${getId()}`:
return 'ViewThreeComponent'
default:
return 'fail'
}
}
console.log(test('/view3/1234567'))

Nested map is not rendering the Redux State Correctly

I am new to react js. I am creating a comparison between user typing and actual sentence to be typed Somehow I am able to achieve this but It is not perfect like nested map is not rendering properly if letter typed correctly it should render green background My state is updated properly But my nested map Kinda not working there is a delay
Component Code
renderLine = () => {
let test = this.props.test.get('master')
return test.map(line => {
return line.check.map( (ltr,i) => ltr.status ? <span key={i} className="correct">{ltr.letter}</span> : ltr.letter )
})
};
handleKeyPress = e => {
if(e.charCode === 32) {
this.setState({
pushToNext:true,
currentTyping:""
})
}
};
handleInput = e => {
if(e.target.value !== " "){
let {storeValue} = this.state;
console.log(storeValue.length);
let updatedWord = e.target.value;
let updateArr = [];
if(storeValue.length === 0){
updateArr = storeValue.concat(updatedWord)
}else {
if(this.state.pushToNext){
updateArr = storeValue.concat(updatedWord)
}else {
storeValue.pop();
updateArr = storeValue.concat(updatedWord);
}
}
this.setState({
currentTyping:updatedWord,
storeValue:updateArr,
pushToNext:false
},() => {
let {storeValue} = this.state
let lastWordIndex = storeValue.length === 0 ? storeValue.length : storeValue.length - 1;
let lastLetterIndex = storeValue[lastWordIndex].length === 0 ? storeValue[lastWordIndex].length : storeValue[lastWordIndex].length - 1;
let lastWordValue = storeValue[lastWordIndex];
let lastLetterValue = lastWordValue[lastLetterIndex];
// console.log(lastWordIndex,lastLetterIndex,lastWordValue,lastLetterValue,"After tstae")
return this.props.compareCurrentTextWithMater(lastWordIndex,lastLetterIndex,lastWordValue,lastLetterValue)
});
}
};
Redux Reducer
import {FETCH_USER_TYPING_TEXT,COMPARE_TEXT_WITH_MASTER} from "../actions/types";
import {fromJS} from 'immutable';
const initialState = fromJS({
text:null,
master:[],
inputBoxStatus:false
});
export default function (state = initialState,action) {
switch (action.type){
case FETCH_USER_TYPING_TEXT:
return setTextManipulated(state,action);
case COMPARE_TEXT_WITH_MASTER:
return compareTextWithMaster(state,action)
default:
return state
}
}
const compareTextWithMaster = (state,action) => {
let {lastWordIndex,lastLetterIndex,lastLetterValue} = action;
let masterWord = state.get('master')[lastWordIndex];
let masterLetter = masterWord.check[lastLetterIndex];
let newState = state.get('master');
if(typeof masterLetter !== "undefined"){
if(masterLetter.letter === lastLetterValue){
masterWord.check[lastLetterIndex].status = true;
newState[lastWordIndex] = masterWord;
return state.set('master',newState)
}else {
masterWord.check[lastLetterIndex].status = false;
newState[lastWordIndex] = masterWord;
return state.set('master',newState)
}
}else {
console.log('Undefinedd Set Eroing or wrong Space Chratced set Box Red Colot',newState);
}
};
UPDATE
I did the same Logic with plain React.js it works Perfectly and nested map rendering the if else logic properly there is no on letter delay
https://codesandbox.io/s/zx3jkxk8o4
But the same logic with Redux State with immutable js Does'nt take effect with nested loop if else statement I don't know where the problem Relies ..and My Code Snippet will be little bit different from CodeSanbox COde But the Logic is Same
Probably, the diffing algorithm of react does see that oldState === newState and skips the re rendering. To avoid that situation, use a new object in the root of the state so that the above check returns false. I see that you use immutableJs, so maybe force re-render with componentShouldUpdate method instead.
Also consider using dev tools to step through the code line by line to see what is going on.
If nothing at all works, switch to something simpler with less dependencies and go from there, incrementally adding what you need.

Categories

Resources