Maximum call stack size exceeded from loop - reactjs

I'm in the early stages of producing a rectangle SVG that uses the rectangle shape. I'm generating the colours of the pixels using a loop that gets all the RGB colours in increments of 8. The returned array has 32,768 <rect /> in it. The code produces the desired outcome however I get an error in:
Chrome
Maximum call stack size exceeded
getTypeSymbol (react_devtools_backend.js:4828)
Firefox
too much recursion
From what I can tell this isn't a recursion problem, the function doesn't appear to be reloading. I think it's related to the size of the array.
Any thoughts on what I should do here, I've never seen this problem before.
function PixelColour() {
console.log("start");
let counter = 0;
let x = 0;
let y = 0;
const colours = [];
for (let red = 0; red < 256; red += 8) {
for (let green = 0; green < 256; green += 8) {
for (let blue = 0; blue < 256; blue += 8) {
counter++;
if (x < 256) {
x++;
} else {
x = 0;
}
if (x === 256) {
y++;
}
colours.push(
<rect
key={counter}
x={x}
y={y}
height="1"
width="1"
style={{ fill: `rgb(${red}, ${green}, ${blue})` }}
/>
);
}
}
}
return <Fragment>{colours}</Fragment>;
}
class Colours extends React.Component {
render() {
return (
<div>
<svg width="256" height="128" style={{ border: "2px solid black" }}>
<PixelColour />
</svg>
</div>
);
}
}

It's not your function reloading (or rerendering) which is the problem per se; you're running into recursion within React itself. Specifically with the way that React devtools tries to reconcile the DOM in order to build a component map.
This is actually not so easy to replicate on codesandbox, since it appears to be using an experimental version of devtools, and this error only crops up when hot-reloading. The stack trace there is scheduleFibersWithFamiliesRecursively but on my local machine with the standard devtools extension installed I get mountFiberRecursively when the component mounts.
I did some digging and came across this github issue, and a PR addressing it which appears to have been abandoned for the time being.
Perhaps if you go and give them a nudge they might take another look:
Getting maximum call stack exceeded on backend.js when rendering many elements.
Refactored backend renderer to remove most of the recursion
All you can do in the meantime is disable the devtools extension. I would add that even with it disabled, this component takes several seconds to mount on my local machine. If you don't take the calculation out of the render cycle (function body) then it is going to be run on every render. You're trying to mount 10s of thousands of DOM nodes which is never going to run performantly - even the PR above only supposes a limit of 15000.
I think a better idea would be to 1) calculate this well in advance if you can, perferably as hard-coded data and nowhere near the UI thread, and 2) draw to a canvas rather than creating nodes in the DOM.

Related

setTimeout in React after render

This is my first question. Anyway, I am new to React, I started 2 weeks ago.
I am making a flipbook where updateAll updates all allPages in the book.
The problem is that when the page is flipped, the z-index needs to be changed in order to adhere to the correct stacking.
When flipping right, we see the z-index of the page on the right change too quickly, and the flipping isn't smooth. Go check it out yourself to see what I mean.
https://cookbookreact.netlify.app/
I need to use setTimeout to set the z-index 200 milliseconds after the page is flipped, so that the page flipping is smooth. But how? I know I need to use useEffect() I think. Right?
Whenever I try to use useEffect(), it says I am breaking the rules of hooks, so I don't even know what to do.
The last z-index needs to be updated so that we can scroll on that page by the way.
// we update any pages that were flipped
updateAll((prevAllPages) => {
for (let i = 0; i < amount; ++i) {
// flip current page
prevAllPages[pageNum + i].isFlipped =
!prevAllPages[pageNum + i].isFlipped;
// zIndex
prevAllPages[pageNum + i].zIndex =
999 + prevAllPages[pageNum + i].pageNum;
}
return prevAllPages;
});
/*** Set timeout goes here ***/
setTimeout(function () {
// so that last page can be seen
updateAll((prevAllPages) => {
if (pageNum < maxPages / 2) {
prevAllPages[pageNum + amount].zIndex =
999 + prevAllPages[pageNum + amount].pageNum;
}
return prevAllPages;
});
// then we update the page number
updatePageNum((prevPageNum) => {
return prevPageNum + amount;
});
}, 200);
I'd appreciate any help, Thank you
David
When updating state try creating a new variable to return instead of changing the prevAllPages and returning it again.

Tensorflow.js BodyPix very slow in browser for single image

I'm trying to create an in-browser background removal using tensorflow.js body-pix
While the online demo reaches ~10 frames per second on my computer, my code takes ~3 seconds for a single frame.
I mostly followed the example on the official github
Here is my code:
const remove_background = async (img) => {
console.time("ML");
console.time("loadModel");
const net = await bodyPix.load({
architecture: 'MobileNetV1',
outputStride: 16,
multiplier: 0.5,
quantBytes: 2
});
console.timeEnd("loadModel");
console.time("segmentPerson");
const segmentation = await net.segmentPerson(img.imageData, {
segmentationThreshold: 0.7,
internalResolution: 0.25
});
console.timeEnd("segmentPerson");
console.time("ApplyMask");
for (var i=0;i<segmentation.data.length;i++) {
if(segmentation.data[i] === 0) {
img.imageData.data[i*4] = 255;
img.imageData.data[i*4+1] = 0;
img.imageData.data[i*4+2] = 0;
}
}
console.timeEnd("ApplyMask");
console.timeEnd("ML");
return img;
}
And here are the times:
loadModel: 129.35498046875 ms
segmentPerson: 2755.817138671875 ms
ApplyMask: 4.910888671875 ms
ML: 2890.7060546875 ms
I started with a 1700x1700 Image with internal resolution of 0.1, and worked down to a 200x200 image with 0.25 resolution, with no significant improvement.
What am I doing wrong?
I'm using tfjs#1.2 & body-pix#2.0
I have found in my implementation using bodypix that the first detection takes quite a bit longer than subsequent ones. I believe they do one-time initialization on the first call to segmentPerson. We are segmenting video. I found I could save about 500ms of startup time of the first detection just by passing a blank image to segmentPerson while the stream is being acquired before passing the video frame by frame when the stream has started.

How do I repeat one image a bunch of times to fill up a page in React JSx?

I'm playing around in React and I was interested in creating an interactive background where this ONE image is repeated (and they rotate, but I figured out how to rotate it). I'm pretty sure there is no way for me to use a for loop also, not sure how to make this happen if it is a background image. I figured I would just use z-index to layer it in the end. So far, I just need help repeating it without using .map()
This is what I have (obviously, it's not working with the for loop):
return (
<div>
{
for (var i = 0; i < 100; i++) {
return (
<img
key={i}
src={circle}
alt="circle"
className="rotate"
/>
);
}
}
</div>
);
What am I not getting? Shouldn't there be a way to use map without having to copy an image over and over again manually into an array. I feel like that defeats the purpose.
You should use css for that.
background-repeat property should be a good solution for your problem.
https://developer.mozilla.org/en-US/docs/Web/CSS/background-repeat
Also, it is not possible to have for loops within JSX code.
Check out this lesson to better understand what you can put there:
https://egghead.io/lessons/react-understand-and-use-interpolation-in-jsx
If you have a need to use for loop for another purpose this is the way I would suggest doing it:
https://codesandbox.io/s/beautiful-hermann-uoro8?file=/src/App.js
function ElementsList() {
const elements = [];
for (let i = 0; i < 5; i++) {
elements.push(<div key={i}>el {i}</div>);
}
return elements;
}
export default function App() {
return (
<div className="App">
<h1>Generate componets using `for` loop</h1>
<ElementsList />
</div>
);
}

Checking shot collisions and removing shot and target in AS3

Last year was my first successful year in teaching my students to create catch and avoid games in Flash with AS3. This year is getting better. Each year I come here for help at least once.
I'm trying to add shooting into the possibilities for their second game project. I can make the shot happen from the ship, gun, whatever, and make it move, and get rid of it when it is off screen, but have not figured out a clean way to have both the shot and the target go away (removeChild and array.splice) upon collision.
The code I have sort of works, but I keep getting the error,
TypeError: Error #1010: A term is undefined and has no properties. at
DropShootV02_fla::MainTimeline/checkShots()
.
Normally I know that this is because of a mismatch between objects and index numbers, but this is related to the call to a second array in removing boxes and bullets.
For simplicity I'll just include the shooting code. Similar organization creates and drops the boxes.
Any help is appreciated. BTW we are not using external script in an AS file.
var shotSpeed = 18;
var shots:Array = new Array();
import flash.events.MouseEvent;
import flash.events.Event;
stage.addEventListener(MouseEvent.CLICK, fireLaser);
function fireLaser(e:MouseEvent):void
{
if (gameOn==true)
{
var shot:Shot=new Shot();
addChild(shot);
shots.push(shot);
shot.gotoAndStop(1);
shot.x = user.x;
shot.y = user.y;
trace(shots.length);
}
}
addEventListener(Event.ENTER_FRAME, moveShot);
function moveShot(e:Event):void
{
for (var i:int=shots.length-1; i>=0; i--)
{
shots[i].y -= shotSpeed;
if (shots[i].y < -25)
{
removeChild(shots[i]);
shots.splice(i,1);
}
}
}
addEventListener(Event.ENTER_FRAME, checkShots);
function checkShots(e:Event):void
{
for (var i:int=shots.length-1; i>=0; i--)
{
for (var k:int=boxes.length-1; k>=0; k--)
{
if (shots[i].hitTestObject(boxes[k]))
{
if (boxes[i].type == "good")
{
score--;
scoreDisplay.text = "Score:" + score;
}
if (boxes[i].type == "bad")
{
score++;
}
removeChild(boxes[k]);
boxes.splice(k,1);
//if I leave this part out I get no errors,
//but but the bullet goes on to strike again
removeChild(shots[i]);
shots.splice(i,1);
}
}
}
}
Thanks kaarto:
I had tried that previously and kept getting the same error. I used that elsewhere in this game code. Turns out I needed to moderate how often the player was shooting. I changed from shooting with the mouse to using space instead and now the problem is gone. Break is definitely a good one here.
Merge move shot and checkShots in one ENTER_FRAME handler.

LESS dynamic variables in nested loops

I'm trying to achieve in LESS loops something in JS or PHP would be really simple. Lets say I have 4 levels to loop. Each level height depends on previous level height. Something like:
for (var i; i < 4; i++) {
if (i = 1) {
var height = 100 * i;
} else {
height = height * 3 - i * 20;
}
}
assignFinalHeight(height);
Is it even possible to achieve in LESS?
Tried guarded mixins something like this:
#height: 0;
.count(#lvl) when (#lvl > 1) {
.for(4); .-each(#lvl) {
#height: #height * 3 - #lvl * 20;
}
}
.count(#lvl) when (#lvl = 1) {
#height: 100 * #lvl;
}
.for(4); .-each(#lvl) {
.count(#lvl);
.lvl_#{lvl} {
height: #height;
}
}
Hope you get the idea.
I also tried some other techniques, but I get errors of recursive variable or I get generated CSS with first two levels correct and all other levels the same as second one.
Any help is appreciated
I'm trying to make something like a playoffs scheme - http://i.imgur.com/J8frRVg.png. All marked 2 team holders are div's with some css classes. All these holders are wrapped in one div. Like
<div>
<div class="holder lvl_1 pos_1">
<div class="team_1"></div>
<div class="other stuff"></div>
<div class="team_2"></div>
</div>
<div class="holder lvl_1 pos_2">...</div>
<div class="holder lvl_2 pos_1">...</div>
...
</div>
The only thing left, is the height and positions from top, but these depend on previous level height. Probably I will just make it in JS if it's not possible in LESS :/

Resources