Does too many switch statements lower performance? - javascript

I'm learning React and am trying to make a component that displays an image dependent on props (game) passed through it. So far I'm using a switch statement that changes the source of the image, but I'm expecting to have a lot more cases than just 2 in the future. In all the switch examples I've seen online they only use like maybe 7 different cases. Is 50+ switch cases too much and will lower performance? I'm pretty new to coding and am wondering if this method is inefficient for lots of cases...
<Pictures game=""/>
Pictures Component
import A from './images/game1.jpg'
import B from './images/game2.jpg'
function Pictures(props) {
let source;
switch(props.game){
case 'game_1':
source = A;
break;
case 'game_2':
source = B;
break;
}
return (
<div>
<img src={source} alt="First slide"/>
</div>
);
}
export default Pictures;
What I tried is technically working, but I'm not sure if it will make load times too long with 50+ cases.

Related

How is this navigation made possible?

I have a quite clear idea in mind for the underlying flow / features for a webpage (module) I'd love to build!
Example here!:
I really like this way of navigating, using left / right arrow keys between columns. And the branching structure of the "cards".
I've been learning more Web development as of late, but I thought to seek some guidance before I step full on into it. I'm mostly familiar with Angular and have briefly touched React... But I'm open to learning pretty much anything. How should I go about approaching making, i.e., a blog with this form of navigation and topical-branching? Any pointers, to tools, similar solutions, could be anything, would be greatly appreciated:)
I’ve tried picking the website above apart, but it didn’t take me far. I am having a real hard time finding out what the correct search terms are, so now I'm mostly just broadly scanning the field of different web applications trying to find if there are better ways to describe what I’m thinking about.
Just use rxjs operator fromEvent
export const LEFT_ARROW = 37;
export const UP_ARROW = 38;
export const RIGHT_ARROW = 39;
export const DOWN_ARROW = 40;
finished: Subject<any> = new Subject<any>();
ngOnInit()
{
fromEvent(document,'keydown').pipe(
takeUntil(this.finished)
filter((key:any)=>key.keyCode>=LEFT_ARROW && key.keyCode<=DOWN_ARROW)
).subscribe((key:any)=>{
switch(key.keyCode)
{
case LEFT_ARROW:
...
break;
case RIGHT_ARROW :
...
break;
...
}
})
}
ngOnDestroy() {
this.finished.next();
this.finished.complete();
}

Fall back image with SvelteKit

I got started with Svelte(Kit) and I really like it so far. However, I ran into an issue that I couldn't resolve.
I'm trying to dynamically display images and like to have a fall back image in case the normal one does not exist.
With vanilla HTML/JS, I would use this Source:
<img src="imagefound.gif" onerror="this.onerror=null;this.src='imagenotfound.gif';" />
I tried to make it happen in my Svelte project, but it either does not work (e.g. A) or it works sometimes (for a brief moment or until I refresh (e.g. B)).
This is my code (A):
<script>
let profileImg = person.profile;
const missingProfile = () => {
console.log('image does not exist');
profileImg = '../default.png';
};
</script>
...
<img
src={profileImg}
on:error={missingProfile}
alt={person.name}
/>
or just the hardcoded version (B)
<img
src="imagefound.gif"
onerror="console.log('image not found');this.onerror=null;this.src='./person.png';"
/>
There is this question, but I believe the answer is what I am doing. Is there a difference whether I use SvelteKit vs. Svelte?
Addition
It looks like that Svelte does not even set the src for the <img />, if the original variable with the url for the image is undefined (in my example person.profile). The accepted answer wouldn't work in that case.
I edited this line to prevent that case:
let profileImg = person.profile === undefined ? '../default.png' : person.profile;
This code works in SvelteKit
<script>
let fallback = 'http://placekitten.com/200/200'
let image = ""
const handleError = ev => ev.target.src = fallback
</script>
<img src={image} alt="" on:error={handleError}>

React: UI not painted correctly with dhtmlx-gantt library when applied with filters

I am using React with dhtmlx-gantt library to create gantt chart. I met with issue when using the filter function together with useEffect/useLayoutEffect lifecycle.
The gist of it is that the browser is not painting/rendering the correct UI on the screen on certain condition.
The start state load screen looks like this:
6 Task
After filter, this should be how it looks like:
Should be left with 5 task after filtering away duration > 4
But this is how it is:
Left with 5 task but an empty row is shown rather than "refreshing" (not sure if this is the right term to use)
I have created a github repo with different scenario describing the problem, and how to reproduce those issue. More information on how to run the sample can be found in the README.md. Please let me know if more information needs to be provided.
Sample 1: Using conditional rendering will cause issue on painting UI changes
Sample 2: Turning smart_rendering config on and off cause issue on painting UI changes
Sample 3: Calling the function within the parent component and in child component with exact same code cause issue on painting UI
My desired outcome is to able to render the UI correctly, whether or not this code to filter the data is ran on parent or child component.
I should also mention that a workaround was to use if (document.querySelector(".gantt_grid")) gantt.render(); rather than gantt.refreshData() in onBeforeTaskDisplay event which will then correctly paint the UI changes. But I still like to understand why does this happens. Is there anything I did wrongly in term of using the React lifecycle and so on.
Thank you.
Your code looks fine and should work correctly.
The issue is on dhtmlxGantt end, it has been confirmed and is now fixed in the dev branch.
The bug itself was caused by the new smart rendering mechanism introduced in v6.2.0.
It caches previously calculated positions of tasks in order to minimize calculations. In certain circumstances when a gantt instance has been initialized multiple times, it didn't invalidate that cache when it was necessary. Because of that, tasks were displayed at the same positions as they had before filtering was applied (thus the blank row where the first task has been).
In short, the issue will be fixed in the next bugfix update - v6.2.6.
If everything goes as planned, it will be released tomorrow (2019-09-19)
Try gantt.render() after gantt.refreshData() in your code:
useEffect(() => {
const onBeforeTaskDisplay = gantt.attachEvent("onBeforeTaskDisplay", function (id, task) {
console.log("filters", task.text, filter)
if (filter && task.duration > 4) {
return false;
}
return true;
});
gantt.refreshData();
gantt.render();
// This should have been here
return () => {
gantt.detachEvent(onBeforeTaskDisplay);
}
}, [filter])

React.js: javascript vs reactjs DOM manipulations

I am new to React.js. I am trying to quantify the time html document takes to render fully. Somebody please tell me where my approach is wrong, I find the results are not comparable at all.
Using React
var UList = React.createClass({
setText: function(){
var updatedItems = this.state.items;
var item = Math.abs(Math.random().toString().split('')
.reduce(function(p,c){return (p<<5)-p+c})).toString(36).substr(0,11);;
updatedItems.push(item);
this.setState({items: updatedItems});
},
getInitialState: function(){
return {
items: []
}
},
render: function(){
return (
<div id='component'>
<button id='bb' type="button" onClick={this.setText}>Set</button>
<List items={this.state.items}/>
</div>
);
}
});
var List = React.createClass({
render: function(){
return (
<ul>
{
this.props.items.map(function(item) {
return <li key={item}>{item}</li>
})
}
</ul>
)
}
});
ReactDOM.render(<UList text="kiran"/>, document.getElementById('container'));
console.log(new Date());
for(var i=0;i<1000;i++)
document.getElementById("bb").click();
console.log(new Date());
Using Javascript
setText = function(){
var item = Math.abs(Math.random().toString().split('')
.reduce(function(p,c){return (p<<5)-p+c})).toString(36).substr(0,11);
var node = document.createElement("LI");
var textnode = document.createTextNode(item);
node.appendChild(textnode);
document.getElementById("myList").appendChild(node);
};
console.log(new Date());
for(var i=0;i<1000;i++)
document.getElementById("bb").click();
console.log(new Date());
In this particular case, react may be slower overall in processing the 1000 clicks. What you are in essence measuring is more or less cycle time between 1 click and 1 update. In your one-to-one comparison direct javascript DOM updates are likely to be faster (maybe directly rendering HTML from server would be even faster).
Some notes:
Cycle time is not the only factor in comparing performance: when doing DOM updates, react in many cases leaves more CPU time available for the user, e.g. to scrolling while react is updating. This in not measured by your test.
Where react really shines is in doing updates: if you delete, update, add many different items in the list of 1000, react is likely to be much faster than the pure-javascript variant.
UPDATE:
One of the key reasons for facebook to build react is because typical DOM updates are really slow. So react minimizes DOM updates, through its diff engine.
If you want to know more about performance, look here for comparison of react vs angular vs knockout.
This video from an angular conference made me aware that there is much more to performance than cycle time: how different processes behave during one cycle has important implications as well.
A sample test version (nice and clean) Rich Ayotte here, compares react also with raw javascript. It shows that raw javascript is actually faster than react (in rendering a long list).
The bottomline:
for small and simple applications, raw is probably faster
but if you want to maintain performance also if your application grows bigger and more complex, react is a safe bet.

AngularJS app freezes when loading in new data to $scope

This is probably a difficult question to answer as I'm not sure what the root problem is here, would appreciate if someone would take a look though.
http://threadfinder.net/search%3FnameTags=jacket/0
If you continually scroll down, more items are loaded in using ngInfiniteScroll and this function:
$scope.moreProducts = function() {
if ($scope.busy || $scope.noMore){return;}
else
if (!($scope.busy)) {
$scope.busy = true;
$scope.itemsLoaded += 27;
var theQuery = $routeParams.query.replace(/\?|%3f/gi, '');
$scope.itemSearch.get({
query: theQuery,
page: $scope.itemsLoaded
}, function(data) {
if (data.posts.length <= 0) {
$scope.noMore = true;
} else {
$scope.noMore = false;
for (var i = 0; i < data.posts.length; i++) {
if ($scope.user) {
if (!($scope.user.likes.indexOf(data.posts[i]._id) === -1)) {
data.posts[i].liked = 'http://i.imgur.com/CcqoATE.png';
} else {
data.posts[i].liked = 'http://i.imgur.com/tEf77In.png';
}
$scope.posts.push(data.posts[i]);
}
}
$scope.busy = false;
}
});
}
}
(I'm using AngularJS Deckgrid for the tile layout, but I've tried disabling it and there is no big change in performance.)
If you keep scrolling, after you get to ~300 items loaded on the page performance starts to take a hit and the app freezes while new items are being loaded into scope.
I understand that perhaps it's just a fact that loading in all this data takes a big load on the page - with every 27 items loaded in (one infiniteScroll GET call) the total weight of the data being loaded in is about 30kb a pop, so at around 300 items there's ~900kb of data in scope. This data is as little as I can make it (~500 lines of JSON).
The question is:
Are there any recommendations, plugins, directives or best-use practices for AngularJS for when loading a lot of data in the page $scope?
For clarification, the app is built on Node/ExpressJS/MongoDB
EDIT: I've checked out this issue on two computers (both on OSX) and this issue is MUCH more prevalent in Chrome than in Safari. Chrome totally staggers when loading in the data, Safari is really smooth and only has any noticable lag when you get to 600+ items and even then it's nowhere near as bad as Chrome.
I took a look at the page with AngularJS Batarang, and it doesn't appear that your app is spending a lot of time in the digest cycle. If you take a look at Chrome's "Timeline" panel during the periods of UI lag, you can see the following:
(full size)
Most of the time is spent in lots of "Parse HTML." A quick Google searched turned up this Stack Overflow question, which has some answers that may be useful; in particular, the Groups post about manual string concatenation by be worth trying here. You may also consider trying to break up the big block of HTML parses into smaller chunks by adding new items to the scope in small batches (perhaps using $evalAsync or a few timers) to see if that helps.

Categories