I am trying to understand why this results in a loop :
<button onClick={this.moveRight()}>
but this does not:
<button onClick={this.moveRight}>
Also my my problem is to call a function from another function that is also resulting a loop, why ?
anyfunction(){
anotherfunction();
}
anotherfunction(){
if (this.state.something >1 ){
this.setState(PrevState => {
PrevState.something = PrevState.something -1
return {something = PrevState.something};
});
this.anyfunction()
}
}
Why the if does not break the loop ?
If this.moveRight() calls itself, then unless you put a condition to stop the recursion, it'll continue to do so. Also, this answer tells you how to assign an event handler correctly.
Also my problem is to call a function from another function. That is also resulting a loop, why?
this.setState is async, so if you want the value of this.state.something to be set before you call this.anyfunction(), then you'll need to do something like:
function anotherfunction() {
if (this.state.something > 1) {
this.setState(
PrevState => {
return { something: PrevState.something - 1 };
},
() => {
this.anyfunction();
}
);
}
}
which says that call this.anyFunction once you're done doing the state change that I asked for. More on that here.
The reason why
<button onClick={this.moveRight()}>
results in a loop is having the parenthesis calls the function, rather than setting onClick to the functions reference.
The second issue is also resulting in a loop because the function's both call each other, if this.state.something > 1 never evaluates to false.
Related
The question seems simple, but it doesn't work for me :(
I am adding listeners depending on the conditions.
If the first condition is true, I add a function
ref.current.onclick = ()=> {function1()}
If the second condition is true, I add the second function
ref.current.onclick = ()=> {function2()}
This removes the first function. How to add a second function without deleting the first?
I tried:
ref.current.onclick = ()=> {ref.current.onclick, function2()}
ref.current.onclick = ()=> {ref.current.onclick(), function2()}
ref.current.onclick = ()=> {()=>ref.current.onclick(), function2()}
This does not work
Something in my question confuses readers)
I have no problem with conditions.
I can't add a second function to the onClick event without removing the first one.
You could use a conditional (ternary) operator like this:
{YourCondition ? ref.current.onclick = ()=> {function1()} : ref.current.onclick = ()=> {function2()}}
For more informations, click on this link to see the full documentation about conditional rendering, which will help you.
I wasn't able to communicate this point clearly in the comments, so here is an example. Without more context of your problem (what is your "condition"?) it is hard to know if this solves your problem or not. Hope it helps though.
Below is a react component that has conditional behavior when you click "Process Number".
If the number is odd, function A gets called.
If the number is even, function B gets called.
But, the onClick function is always the same: "processNumber"
The key concept here is the processNumber function that is able to handle the condition and call A or B accordingly. You could add all kinds of logic in here, but the onClick would always point to processNumber, not some other function.
//EvenOddComponent.js
import { useState } from 'react';
export default function EvenOddComponent() {
const [number, setNumber] = useState(1)
function A() {
console.log('the number is odd')
}
function B() {
console.log('the number is even')
}
function processNumber() {
if (number % 2 != 0) {
A()
} else {
B()
}
}
return <div>
<>{number}</>
<button onClick={() => setNumber(number + 1)}>Increment Number</button>
<button onClick={processNumber}>Process Number</button>
</div>
}
An alternative solution could be to pass the onClick function in as a prop like this:
export default function funcCaller(props) {
return <button onClick={props.functionToCall}>Do thing</button>
}
Here's my code. What i want to check is that all the elements processed in the do, or not. The reason is that in the kategoriak array, only one of it's object has szint: 1. But it's possible that this element is at the end of the array. I want to do the process until every element has a szint which is not 0. But it don't matter. My question is that what am i doing wrong at the while? The code should work, but it's an infinite loop. Any ideas?
do{
kategoriak.forEach(elem => {
elem.child.forEach(child => {
kategoriak.forEach(ell => {
if(child === ell.id && elem.szint !== 0){
ell.szint = elem.szint + 1
}
})
})
})
} while(
() => {
kategoriak.forEach(elem => {
if(elem.szint === 0){
return true
}
})
return false
}
)
You can give while a function, but while isn't going to call your function. It will regard a function as a truthy value and hence continue endlessly. You'll have to call your function yourself. But really, that is nonsense, you just have to use an expression which results in true or false, in this case Array.prototype.some is what you're looking for:
do {
...
} while (kategoriak.some(elem => elem.szint === 0));
(Whether this is the best approach to this problem in the first place I dare not say.)
Inside the while(...) you define a function but not call it. Thus, the function expression itself is the condition, which is always true. You need to also call your function. i.e.
do{
...
} while(
(() => {
kategoriak.forEach(elem => {
if(elem.szint === 0){
return true
}
})
return false
})(); // Notice the parentheses we use to call the function
)
An even better way to implement this would be using Array.prototype.some. It is a method that returns true when some of the elements satisfy the given function.
do {
...
} while (kategoriak.some(elem => elem.szint === 0))
I am trying to remove item from a node in for each loop on my cloud function. But it always looking only first item. I want to loop all items. Here is my codes:
snapshot.forEach(function(child) {
console.log('all items');
return thisAppDb.ref('userRemindMatches/'+child.key+'/'+compId).once('value').then(snapshot => {
if (snapshot.exists()) {
snapshot.ref.remove();
console.log('match removed from this user : '+child.key);
}
return thisAppDb.ref('user : '+child.key+' matches removed');
});
});
As you see here, in snapshot.foreach, I am calling another ref. Node then I want to remove item from that node. It is working only once. How can I loop this for each items? (In my opinion, it occurs because of return in loop)
change this:
return thisAppDb.ref('userRemindMatches/'+child.key+'/'+compId).once('value').then(snapshot => {
to this:
return thisAppDb.ref('userRemindMatches/'+child.key+'/'+compId).on('value',(snapshot)=> {
The documentation for forEach makes it clear how the return value from your passed function is interpreted:
function(non-null admin.database.DataSnapshot)
A function that will be called for each child DataSnapshot. The
callback can return true to cancel further enumeration.
You're returning a "truthy" value, which tells forEach to stop.
I have a code that works fine:
myService.myFunc1()
.then(myService.myFunc1)
.then(function(dataA) {
// do something
})
.then(myService.myFunc2)
.then(function(dataB) {
//do something
});
However, upon myFunc1 execution, the value for boolean myService.trig is set properly. I'd like to change the code above to make it conditional based on the myService.trig boolean value and decide whether to execute all the rest .then (for true) after myService.myFunc1(). or execute one another .then INSTEAD (for false).
How can it be done in angularJS way?
Thank you.
I think you will have to check in every callback what the value of ``myService.trig` is.
myService.myFunc1()
.then(() => {
// execute this function if the "myService.trig" is true
if (!myService.trig) return;
return myService.myFunc1;
})
.then((dataA) => {
// execute this function if the "myService.trig" is true
if (!myService.trig) return;
// do something
})
.then(() => {
// execute this function if the "myService.trig" is false
if (myService.trig) return;
return myService.myFunc2;
})
.then((dataB) => {
// execute this function if the "myService.trig" is false
if (myService.trig) return;
// do something
});
Or you could nest the promises so you don't have to check for the value all the time. But to he honest, I would prefer the repeated checking than nesting promises.
Consider the code snippet below:
function isUniform(myArray) {
myArray.forEach(function(element) {
if (element !== myArray[0]) {
return false;
}
});
return true;
}
The intention is that the function should take an array as input and return true if all the elements in the array are the same and false otherwise.
eg:
isUniform([1,2,1,1]); // should return false
isUniform([1,1,1,1]); // should return true
However, the if condition:
if (element !== myArray[0])
never seem to be true in the case of isUniform([1,2,1,1]).
What is it that I am missing ?
So the return true isn't returning a value for the function isUniform, it's returning a value for the callback that you provided to the forEach method. forEach is really only used to create side effects. So forEach executes the callback on each element, sees that the callback returns false, but then doesn't have anything to do with that value, so it throws it out and moves on to the next element in the array. After iterating through the array, it moves on to the next line of code and returns true for the function.
One way that you might do this using forEach is to declare a variable that you initialize as true and manipulate that within the callback. This is necessary, as there's not a way to end the execution of a forEach loop early. So you might instead use:
function isUniform(myArray) {
var passing = true;
myArray.forEach(function(element) {
if (element !== myArray[0]) {
passing = false;
}
});
return passing;
}
Or you could use a for loop or a for-of loop, in which case the return statement would work as you had originally expected. You're probably already familiar with for loops. For-of loops were introduced in ES2015 (so they might not work on all JS engines). A for-of loop would look like this:
function isUniform(myArray) {
for (element of myArray) {
if (element !== myArray[0]) {
return false
}
}
return true
}
However, the best way to do this is probably using the built in array method every, which returns true if every element in the array passes the test provided in the callback. So you might test every element to see if they're equal to the 0th element in the array and thus equal to each other:
function isUniform(myArray) {
return myArray.every(function (currentElement,index,array) {
return currentElement === array[0]
})
}
That's short enough that you really don't even need to put it in its own function -- and your code will probably be more readable if you don't.
Docs:
Array.prototype.every: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every
For-of loop: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of