I am trying to get a simple ES6 for-loop working but cant figure out why its not running.
I've copied an example from developer.mozilla docs and I've also tried it with the eslinter version which is below:
I have also added a let i = 0; above. All it renders/logs is i = 0 and wont increment.
the eslint version is here: eslint site
for (i = 0; i < 10; i += 1) {
console.log('i', i);
return <p>component {i}</p>;
}
Edit: ok got the values coming back in the log as i=0, i=1, etc... but to get them into a component each? i tried the push into array and mapping through to get the components out but i get no error and nothing appearing, even if i try just getting a value out.
const nbPageArray = [];
let i = 0;
for (i = 0; i < nbPages; i += 1) {
console.log('i', i);
nbPageArray.push(<p>component {i}</p>);
}
console.log('array', nbPageArray);
nbPageArray.map(a => <p>{a.type}</p>);
}
final working version:
const nbPageArray = [];
for (let i = 0; i < nbPages; i += 1) {
nbPageArray.push({ page: i + 1 });
}
return nbPageArray.map(a =>
<li className="page-item"><a className="page-link">{a.page}</a></li>,
);
Main issue is i += 10;
That should be 1 += 1;
And You should return array of elements :
var p_tags = [];
for (i = 0; i < 10; i += 1) {
console.log('i', i);
p_tags.push(<p>component {i}</p>);
}
return p_tags;
Edited question's answer :
First Error:
const nbPageArray = []; should be var nbPageArray = [];
Second You are not returning the array so change your code to this
return nbPageArray.map(a => <p>{a.type}</p>);
If you return from your for loop, you will exit the current function, you are also incrementing i by 10 each trip so you will exit the loop after one round either way.
If you are trying to print a string with the value of i ten times you could try using template string like so:
for (i = 0; i < 10; i += 1) {
console.log('i', i);
console.log(`<p>component ${i}</p>`);
}
you are returning from the loop and also incrementing by 10. The loop will execute only once.
As said in the comments, the return inside the for loop is going to exit from the function at the first iteration.
You can do something like this instead:
const result = Array(10).fill().map((_, i) =>
<p>component {i}</p>
);
Or
const result = [...Array(10)].map((_, i) =>
<p>component {i}</p>
);
Related
how do I pull variables from array one by one? I want to make a card with one saying Zlin, second Praha, etc... The way it works now is that it outputs all of them at once 4x. Thank you.
const KartyLoop = () => {
var mesta = ['Zlin','Praha','Ostrava','Brno']
var lokace = []
for (var i=0; i < mesta.length; i++)
{
lokace += mesta + "\n"
}
return (<Text>{lokace}</Text>);
}
Your code pushes the array itself and not its values.
If I understand correctly you want to copy an array.
You would want to do this.
const KartyLoop = () => {
var mesta = ['Zlin','Praha','Ostrava','Brno']
var lokace = []
for (var i=0; i < mesta.length; i++)
{
lokace += mesta[i] + "\n"
}
return (lokace);
}
I want to make once the code is redeemed it not be able to be used
const codes = ['5345345345345345','23123123123','312312312321q3']
for (var i = 0; i < codes.length; i++) {
if (message.content.includes(`redeem ${codes[i]}`)) {
message.channel.send("YES IT WORKED")
break;
}
}
You can essentially use Array.prototype.splice() to remove elements from the array therefore modifying it, so i would do something like this
const codes = ['5345345345345345','23123123123','312312312321q3']
for (var i = 0; i < codes.length; i++) {
if (message.content.includes(`redeem ${codes[i]}`)) {
// finding index of the code
const index = codes.indexOf(codes[i]);
//splicing from array
codes.splice(index, 1) // splice(index of element, number of elements to delete)
message.channel.send("YES IT WORKED")
break;
}
}
const randomNum = [];
for (let i = 0; i <= 20; i += 1) {
randomNum.push(Math.floor(Math.random() * 20 + 1));
}
then
function getOccurrence(array, value) {
return array.filter((x) => x === value).length;
}
My goal is to print out something along the line of
Number 1, 6, 12, 3, 9 occurred 1 times.
Number 2, 5, 7, 19, 17 occurred 2 times.
Number 15, 11 occurred 3 times.
And so on.
Any idea how i should go about this?
I was thinking of making a function, something along the line of
function numberOccurrence(arr, arrLength){
}
So i in the future could feed it ANY array with with x amount of numbers in it, but I'm unsure how to go forward.
I've tried multiple .includes, .indexOf, ifs and so forth, but i feel stuck, could anyone give me a push in the right direction?
I feel like having a loop which counts how many times 1 occurs, then saves that into an object like this
numObj = {
1: 2,
2: 1,
3: 4,
}
Where the object is built as soon as the function runs, and it builds it based on the arrLength parameter i feed the function in the beginning.
Anything is appreciated, thank you!
Update:
I manage to SOMETIMES print part of the answer right with this:
function getOccurrence(array, value) {
return array.filter((x) => x === value).length;
}
for (let i = 1; i <= randomNum.length; i += 1) {
let numOccurr = [];
for (let j = 1; j <= randomNum.length; j += 1) {
if (randomNum.includes(j)) {
if (getOccurrence(randomNum, j) === i) {
numOccurr.push(j);
if (j === randomNum.length) {
printOut(`Number: ${numOccurr.join(', ')} occurrs ${i} times.`);
numOccurr = [];
}
}
}
}
}
if i check my array after "Number: 20 occurred 4 times" gets printed, i see that the answer is correct, problem is, sometimes it prints every number generated 1 time, then sometimes only those generated 2 times, and so on. And sometimes nothing gets printed
SOLVED:
This code worked for me
const randomNum = [];
for (let i = 0; i < 20; i += 1) {
randomNum.push(Math.floor(Math.random() * 20 + 1));
}
function getOccurrence(array, value) {
return array.filter((x) => x === value).length;
}
for (let i = 1; i <= randomNum.length; i += 1) {
const numOccurr = [];
for (let j = 1; j <= randomNum.length; j += 1) {
if (randomNum.includes(j)) {
if (getOccurrence(randomNum, j) === i) {
numOccurr.push(j);
}
}
}
if (numOccurr.length !== 0)
printOut(`Number: ${numOccurr.join(', ')} occurred ${i} times.`);
}
Building a Sort-Visualizer in React using the Create-React-App [https://roy-05.github.io/sort-visualizer/ ]
I'm animating each iteration of the loop using setTimeouts. On dev console I get the following warning:
Line 156:32: Function declared in a loop contains unsafe references to variable(s) 'minimum', 'minimum', 'minimum', 'minimum' no-loop-func
Here's the code-snippet:
for(let i=0; i<arr.length-1; i++){
let minimum = i; //Declare minimum here
setTimeout(()=>{
for(let j = i+1; j<arr.length; j++){
setTimeout(()=>{
//Getting a warning for these references:
array_bar[j].style.backgroundColor = 'red';
array_bar[minimum].style.backgroundColor = 'blue';
setTimeout(()=>{
if(arr[j] < arr[minimum]){
array_bar[minimum].style.backgroundColor = 'lightblue';
minimum = j;
}
else{
array_bar[j].style.backgroundColor = 'lightblue';
}
}, 4);
}, (j-1)*4);
}
Going through ESLint Docs, I believe the issue might be that i'm modifying the value inside the setTimeout but the variable is declared outside its scope.
I'm not sure how to fix that warning, any help will be appreciated!
Note: Here's the entire function if you need it -
selectionSort(){
const arr = this.state.array,
array_bar = document.getElementsByClassName("array-elem");
this.setState({startedSelectionSort: true});
for(let i=0; i<arr.length-1; i++){
let minimum = i; //Declare minimum here
setTimeout(()=>{
for(let j = i+1; j<arr.length; j++){
setTimeout(()=>{
//Getting a warning for these references:
array_bar[j].style.backgroundColor = 'red';
array_bar[minimum].style.backgroundColor = 'blue';
setTimeout(()=>{
if(arr[j] < arr[minimum]){
array_bar[minimum].style.backgroundColor = 'lightblue';
minimum = j;
}
else{
array_bar[j].style.backgroundColor = 'lightblue';
}
}, 4);
}, (j-1)*4);
}
setTimeout(()=>{
let temp = arr[i],
arr1_height = arr[minimum],
arr2_height = arr[i];
arr[i] = arr[minimum];
arr[minimum] = temp;
array_bar[i].style.height = `${arr1_height}px`;
array_bar[minimum].style.height = `${arr2_height}px`;
array_bar[i].style.backgroundColor = "green";
if(i !== minimum){
array_bar[minimum].style.backgroundColor = 'lightblue';
}
}, 400);
if(i === arr.length-2){
setTimeout(()=>{
array_bar[i+1].style.backgroundColor = "green";
},800);
}
}, i*400);
}
setTimeout(()=>{
this.setState({sorted: true})
}, arr.length*400+1750);
}
I also encountered same warning. In my case, I declared variable outside the iteration, but modified variable inside forEach method.
Something like:
// some code above
let validInputs = true;
someInputs.forEach( input => {
validInputs = input.value && validInputs;
})
After I did some reserch, I found in this post, JSHint error : Functions declared within loops referencing an outer scoped variable may lead to confusing semantics, mentioned that JSHint doesn't like how the anonymous function in there is being re-created over and over.
I changed forEach arrow function to for (let index i = 0; index < someInputs.length; index++), and the warning is gone.
Perhaps in your case, change setTimeout to traditional non-arrow function can remove the warning.
updated on Apr 7th 2021
As I'm reading the Professional JavaScript for Web Developers, 4th edition, I might have found why this warning is implemented in the ESLint.
From section 4.3 Garbage Collection sections, the book mentioned that closure might also lead to memory leak.
The purpose for forEach and arrow function is to limit the scope of the variable, as describes below from MDN:
Arrow functions establish "this" based on the scope the Arrow function is defined within. from Arrow function expressions
In section Creating closures in loops: A common mistake, MDN mentioned:
Another alternative could be to use forEach() to iterate over the helpText array and attach a listener to each , as shown:
function showHelp(help) {
document.getElementById('help').textContent = help;
}
function setupHelp() {
var helpText = [
{'id': 'email', 'help': 'Your e-mail address'},
{'id': 'name', 'help': 'Your full name'},
{'id': 'age', 'help': 'Your age (you must be over 16)'}
];
helpText.forEach(function(text) {
document.getElementById(text.id).onfocus = function() {
showHelp(text.help);
}
});
}
setupHelp();
In our implementation, calling arrow functions inside forEach is creating closure of closure, which obviously can create some confusing semantics for garbage collection.
You're correct that modifying the variable inside setTimeout is causing the issue. You can get around this by wrapping setTimeout inside a promise and waiting for it to resolve before modifying your variables. This is much cleaner using async/await:
for (let i = 0; i < arr.length - 1; i++) {
let minimum = i;
await new Promise(resolve => setTimeout(resolve, i * 400));
for (let j = i + 1; j < arr.length; j++) {
array_bar[j].style.backgroundColor = "red";
array_bar[minimum].style.backgroundColor = "blue";
await new Promise(resolve => setTimeout(resolve, (j - 1) * 400));
if (arr[j] < arr[minimum]) {
array_bar[minimum].style.backgroundColor = "lightblue";
minimum = j;
}
}
}
With each loop, you're creating a promise that resolves once the timeout is expired. Using await will pause execution of your function until the promise resolves. Then, you can modify variables like minimum because they are no longer within the scope of the callback function you were originally passing into setTimeout.
Using typescript and React, I was able to initialize minimum inside of the for loop call, and then reinitialize once I got inside:
for (let i, minimum = 0; i < arr.length - 1; i++) {
minimum = i; //reinitialize minimum here
setTimeout(() => {
for (let j = i + 1; j < arr.length; j++) {
setTimeout(() => {
//Getting a warning for these references:
array_bar[j].style.backgroundColor = "red";
array_bar[minimum].style.backgroundColor = "blue";
setTimeout(() => {
if (arr[j] < arr[minimum]) {
array_bar[minimum].style.backgroundColor = "lightblue";
minimum = j;
} else {
array_bar[j].style.backgroundColor = "lightblue";
}
}, 4);
}, (j - 1) * 4);
}
});
}
For me redeclaring the variables in the timeout function did remove that warning for me in FirebaseFunctions.
setTimeout(async ()=> {
var NumberInst = await admin
.firestore()
.collection("CollName")
.doc('DocName')
.get();
var Numbers = NumberInst.data().postponeX;
}, 1000 * 60 * 11 );
testSed4 = sedenia4.get(0);
while (it8.hasNext()) {
tempRozdiel = it8.next();
tempSed4 = it7.next();
if (testSed4.equals(tempSed4)) {
testSed4 = tempSed4;
casy.add(tempRozdiel);
} else {
casy.add(hodnota);
testSed4 = tempSed4;
}
}
for (int j = 0; j < casy.size(); j++) {
System.out.println(casy.get(j) + " casy");
}
Why I have error in line: tempRozdiel = it8.next();
What is bad in this code ?
Exception happens because you are modifying the collection over which it is iterating within the body of the iteration loop.
This is a reason why you got ConcurrentModificationException from iterator.next()
while (it8.hasNext()) {
tempRozdiel = it8.next();
tempSed4 = it7.next();
You are only checking if it8 has a next element, but not for it7.
Furthermore, you cannot use casy.add() if it7 or it8 are iterators on this object.