Why does onClick={props.onClickFunction(1)}> doest not work ?
Function Button(props) {
// const handleClick = () => setCounter(counter+1);
return (
<button onClick={props.onClickFunction(1)}>
+{props.increment}
</button>
}
Why should I use another function
`
function Button(props) {
const handleClick = () => props.onClickFunction(1)
return (
<button onClick={handleClick}>
+{props.increment}
</button>
);
}
`
When I tried declaring handleclick function it's working .
The difference is perhaps best illustrated by the snippet below, which shows what you're effectively doing in each of your examples.
// top example
handleClick = () => props.onClickFunction(1)
// bottom example
handleClick = props.onClickFunction(1)
You are assigning the result of calling the onClickFunction by mistake, when what you actually want to do is assign a function that calls onClickFunction each time it's called. The following code will also work as intended:
function Button(props) {
return (
<button onClick={() => props.onClickFunction(1)}>
+{props.increment}
</button>
}
When a component renders, all statements are executed and expressions are evaluated.When Component renders props.onClickFunction(1) function is called which returns undefined which will cause the button to render as causing nothing to occur.
handleClick on the other hand is a reference to a function. You need to pass the function reference to onClick and later when the click happens , it can be called later by React.
"Click" is an event so you have to pass an event handler function. When click is detected on the element that handler function will run.
// you are passing an event handler
<button onClick={handleClick}>
But in this case onClick={props.onClickFunction(1)}, you are passing the return value of props.onClickFunction function and if this function does ont return anything, its return value will be undefined.
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>
}
How does react know to provide the event as a second argument in the code below?
const clickMe = (parameter) => (event) => {
event.preventDefault();
// Do something
}
<button onClick={clickMe(someParameter)} />
Does it generate this to:
<button onClick={(event) => clickMe(someParameter)(event)} />
Or how does it work?
Thanks.
Maybe this will help explain it a little better.
Closures are functions that carry the information (variables etc.) from their local environment with them when they're returned.
I'll work this example without arrow functions as they can be a little deceiving.
// `multplyBy` accepts a number as its argument
// It returns a new function that "remembers" that number
// when it's returned. But that new function *also*
// accepts a number
function multiplyBy(n) {
return function(n2) {
return n2 * n;
}
}
// So `multiplyBy(5)` returns a new function
// which we assign to the variable `five`
const five = multiplyBy(5);
// And when we call `five` with a number we get
// the result of calling 5 * 10.
console.log(five(10));
If you substitute multiplyBy(n) with clickMe(n) you'll see that you'll get a new function that gets used by the click listener, and the first argument of that function will always be the event.
Clickme variable in your code is a function which has return is function e => {...}. So when you specify like this:
<button onClick={clickMe(someParameter)} />
it is equivalent to
<button onClick={e => {...} />
which is basic form of a event handler in react
I was reading this article on handling passing down callback functions to memoized React components (using React.memo())
In order to not create a new function every single time the component re-renders, this article recommends to not make that function anonymous, but define it in the parent, and only then pass it down:
function ParentComponent() {
const onHandleClick = useCallback(() => {
// this will return the same function
// instance between re-renders
});
return (
<MemoizedSubComponent
handleClick={onHandleClick}
/>
);
}
This makes sense to me so far. However, in my case I need to pass down some arguments to my handleClick(), so later identify the component.
Until now, I have always solved this problem via arrow functions: So instead of handleClick={onHandleClick} I would normally do handleClick={()=> onHandleClick(i)} - but doing this here would once again create a new function, correct? So I'd be at square 1 again.
How would I ideally solve this?
Edit:
So for example, say I want to do this:
function ParentComponent() {
const onHandleClick = useCallback((itemIndex) => {
console.log(itemIndex);
});
let data = [1,2,3,4]
return (<div>
{data.map(item => {
return <MemoizedSubComponent
handleClick={(i)=> onHandleClick(i)}
/>}
</div>)
}
...but not recreate the arrow function on every single rerender.
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.
With a typical react function, calling the function within an event (e.g. onClick={}) will result in the function being called immediately upon component mount.
For example, this code will fire immediately upon mount because the function is being called:
const App = () => {
const fn = () => {
alert("hey");
};
return (
<button onClick={fn()}>click</button>
);
};
However, if the function uses a closure, it will only execute when the button is clicked. For example:
const App = () => {
const fn = () => {
return () => alert("hey");
};
return (
<button onClick={fn()}>click</button>
);
};
Why does this occur?
To understand what's going on here it might help to substitute the function call with what it's evaluating to (inlining the call). In the first case, it is undefined, as the function does not return anything. While evaluating it's value, it also alerts, resulting in:
alert("hey"); // this is more or less executed here
<button onClick={undefined} >
In the second case, the function returns another function, so that's what it evaluates to:
<button onClick={() => alert("hey")} >
Now a function get's passed to onClick, which will be called when the button is actually clicked.