React: Using arrow function to pass a prop - javascript

In one of my component I am using something like:
<PhotoList update_photo={() => this.update_photo()} />
Here I am passing a function as a props which updates a photo to the state..
and In my photo list component I have list of photos where I am updating the photo like:
<div className="single-photo" onClick={() => this.props.update_photo(photo)}>
Here it is passing undefined instead of photo.. buth when I use it in general way like <PhotoList update_photo={this.update_photo.bind(this)} /> and <div className="single-photo" onClick={this.props.update_photo.bind(this, photo)}> it works
What is the difference and why is the first method not working ??

It's difficult to tell without knowing how this.update_photo() is defined, but I'm guessing the problem is that the function you are passing in takes no argument, but you are trying to pass in an argument from the child.
So perhaps try wiring up the argument like this:
<PhotoList update_photo={(photo) => this.update_photo(photo)} />
Then this.update_photo should be able to set state based on the argument passed into it.

It would be helpful to see how the update_photo() method is defined, but I suspect it has something to do with the fact arrow functions don't bind their own this value. If you're using an arrow function as a method, this will be undefined.

Related

Difference between sending a function as arrow function [duplicate]

This question already has answers here:
What is the logic behind the arrow function behaves differently when taking values?
(8 answers)
Difference between using Arrow function or function for onClick in ReactJS?
(2 answers)
Question: Call the function and passing in an anonymous arrow function that alerts the spliced value
(2 answers)
Closed 5 months ago.
I've seen in many place those two options to do the things but don't know which is the difference more exactly between this:
<Button onClick={doSomething} title='OK' />
and this:
<Button onClick={() => doSomething()} title='OK' />
<Button onClick={doSomething} title='OK' />
You pass the function reference to the onClick event to execute, on my opinion mostly I use it
When I just want to execute one function on the click event.
When I don't need any parameters or just the event parameter.
<Button onClick={() => doSomething()} title='OK' />
you execute the function inside the outer callback, which I usually do when I want to
Execute more than one function on the click.
When I need to pass more parameters to the function than the event parameter.
Some Notes
Just note you can just pass the function reference and use bind() to pass more parameters than the event parameter.
For performance optimization, If you use memo hook with the child component it would be better to use useCallback hook with the function
There is very little difference, in all honesty. The named function option allows you to centrally maintain the logic but prevents you from using it directly in various places where the handler signature may vary.
The arrow function form, on the other hand, allows you to "proxy" disparate event function signatures into your own function. This is something like the Adapter pattern, where you "translate" something (the specific event parameters) into something else (your specific function's parameters).
In short, the arrow function will allow you more flexibility in the long run, but both are the same thing, in essence: Objects of type function.
Furthermore, arrow functions cannot get their this variable redefined. If you ever find yourself in need of this, go for the arrow function variant.
When using this:
<Button onClick={doSomething} title='OK' />
You can't pass parameter to the function.
<Button onClick={() => doSomething()} title='OK' />
With this one you can pass a parameter for example
As #deceze said in the comments: this will receive any argument that you passed from outside not an argument that onClick will pass
<Button onClick={() => doSomething(row.id)} title='OK' />

Passing values outside of array in .map - React

I am working with this piece of code in React where I am mapping over the array "householdNotes", passing "nt" to each component being created. "staffUser" is a hook/variable being stored elsewhere in the code. I would like to pass this value down to the components as a prop. Is this possible in any way?
householdNotes.map(nt => <NoteCard note={nt} user={staffUser} />
)
An option I thought about was passing it through the slug and then grabbing it from match.params, but I'd like to avoid that if possible because staffUser can contain spaces. I don't mind passing the static value of "staffUser" if that also makes this doable. Any ideas?
Thanks for your help, friends!

React unwanted submit on every character inputed

Everytime I enter a character in my input textfield, it automatically presses the submit button attached to it.
I would like to enter all the characters in the input textfield before it submits.
It's this part that is causing a problem:
<input type="text" ref={this.input} onChange={this.handleChange} />
<input type="submit" className="text-success col-offset-3" onClick={console.log("clicked")} value="Add Stock"/>
For example, it will console.log "clicked" everytime I enter a character in the input textfield without me actually clicking the button
Does any one of you guys know why?
Your passing in console.log() so every time the page re-renders the function gets called. As your calling it by passing it in like that.
You need to pass it in like this:
onClick={() => console.log("Clicked")}
<input type="submit" className="text-success col-offset-3" onClick={console.log("clicked")} value="Add Stock"/>
This is calling the console.log function every time the component is rendered. It's probably why you think the form is being submitted every time you type something. You should do something like this:
<input type="submit" className="text-success col-offset-3" onClick={() => console.log("clicked")} value="Add Stock"/>
You can find some more information in the React docs: Handling Events.
Explanation:
The reason why you do this, is that in React you don't include the parenthesis on your events. So in html you would do:
Regular HTML:
<button onclick="myFunc()">Button</button>
But in React you need to do:
JSX:
<button onClick={myFunc}>Button</button>
(Note that in class components you may need to use this.myFunc).
If you use the parenthesis in React, you're actually just calling the myFunc function when that piece of code is run:
This is wrong:
<button onClick={myFunc()}>Button</button>
Now, what happens if the function needs to take some parameters? i.e. what you need myFunc to be called with some number like 123 for example? This is covered in the docs (see Passing Arguments to Event Handlers
), there are two or three ways to go about this:
Create an auxiliary function that calls the function you want to call:
Kind of messy, but I'm including this since it's a valid alternative:
// Somewhere else in your component...
myAuxFunc = () => {
myFunc(123)
}
// Inside your render...
<button onClick={this.myAuxFunc}>Button</button>
Use an arrow function:
This is somewhat similar to creating an auxiliary function. Actually we are doing the same thing, we are creating a function that calls the function we're actually interested in, only that we're not naming it (it's an anonymous arrow function) and we're creating it on the spot:
<button onClick={() => myFunc(123)}>Button</button>
This can be tricky, but it is essentially the same as the first alternative I mentioned. I'm telling react that when the button is clicked, I want the following function to be called: () => myFunc(123). It's a function that takes no parameters, and when it is called, it will call myFunc(123).
(Class components) Use the bind function to bind the this keyword:
This is useful in class components when you want to call functions defined in your components so I'm including this here for completeness. It's not actually useful when you want to call a function like console.log.
<button onClick={this.myFunc.bind(this, 123)}>Button</button>

Whats going on under the hood here for event handler? Does it apply to other functionality?

Hi so I am just wanting to understand how javascript/react is handeling whats going on when I have a function triggered from an event . Im going to show three different code segements, 2 of which work, one of which didnt, and see if I am understanding them correctly. :)
setField(e){console.log("in setfield", e)}
<select multiple className="form-control" id="sel2" name="sellist2"
onChange={() => this.setField()}>
this doesnt work because it is passing a null value to a function that expects a value, in this case e. however, if the function was just submitting something already in state, that would be reasonable way to do it.
setField(e){console.log("in setfield", e)}
<select multiple className="form-control" id="sel2" name="sellist2"
onChange={(e) => this.setField(e)}>
this works because it is getting the event as e and then passes it to the function. How does it know to associate the event to e? does this functionality extent to other things when dealing with html?
setField(e){console.log("in setfield", e)}
<select multiple className="form-control" id="sel2" name="sellist2"
onChange={this.setField}>
This one I really dont understand why it works, but it does. I am assuming that it inherently know to pass the event as default to the function. again does this inbuilt logic occur anywhere else, maybe not neccessarily for events?
Thanks again. Im new to javascript so it is interesting to learn all the idosyncracies of javascript. sadly most of then learning is through frustration of debugging!
All functions in javascript can be passed an arbitrarily large number of parameters, even if the function doesn't do anything with them. For example, the following is legal, if useless:
function thingThatExpectsZeroParams() {
console.log('hello');
}
thingThatExpectsZeroParams(1, 2, 3, 4, [5], 'six');
Six pieces of data were passed into the function, but nothing happened with them because the function didn't do anything with them. To get access to the values passed in, you just need to pick a name that you're going to call it. This name is local to your function and can be anything you want.
function callback(event) {
console.log(event);
}
// I could also just have easily called it something else, and the code would work just as well
// function callback(quesoBurrito) {
// console.log(quesoBurrito);
// }
callback('hello');
So when you set up a listener like this:
onChange={() => this.setField()}
Your function will be called, passing in the event object. But since your function doesn't give the first parameter a name, you have no way to access it, and then when you call this.setField, you pass nothing in there either.
In contrast, with this listener:
onChange={(e) => this.setField(e)}
Your function will again be called, passing in the event object. This time, you named that argument 'e', and can then do with it what you will, in this case forwarding it along to setField.
And when you do this:
onChange={this.setField}
You cut out the middleman. this.setField will get called directly, passing in the event object. Presumably, setField is expecting this, and does something with the object it was passed.
It's not complicated. Whatever Javascript function you assign to onChange will get called at the appropriate time and passed one single argument generally known as e. You can give that argument any name you want in your function (or not declare it at all), but the first argument will be there.
So, when you do this:
onChange={() => this.setField()}
You are ignoring the argument passed to your event handler and then inside that event handler you're calling this.setField() which to no surprise does not pass any argument to setField(). In reality, what's actually happening is this:
onChange={(e) => this.setField()}
How does it know to associate the event to e? does this functionality extent to other things when dealing with html?
The DOM specification says that when an onChange event handler is called, it will be passed the e object as the first argument (whether you declare it or not, it's there as the first argument to the function). This is just how callbacks work in Javascript. The caller of the callback decides what arguments they are going to pass the callback. It's up to you when you declare your callback whether you declare the argument and use it or not. Regardless of how you declare it, the caller passes it.
For this section of code:
onChange={this.setField}
You are say that the function you want to be the onChange event handler is your setField() method. So, no surprise, when the DOM calls that method, it will pass the event object as the first argument just like in the above example.
This one I really dont understand why it works, but it does. I am assuming that it inherently know to pass the event as default to the function. again does this inbuilt logic occur anywhere else, maybe not neccessarily for events?
As described earlier the DOM specification is where this event handler is specified. In the definition of that, it describes what arguments will or won't be passed to whatever callback function you register as this event handler. This is true of all callbacks in Javascript. The caller decides what it will pass to the callback. This is not specific to this type of event handler. Callbacks are used lots of places in Javascript. Even something like array.filter() takes a callback and it's the caller of the callback (the implementation of the Array object in that case) that determines what arguments are passed to the callback.

Calling a javascript function in JSX: why does calling a function without the () work?

Currently on Codecademy and learning about React.
Came to this code:
import React from 'react';
import ReactDOM from 'react-dom';
function makeDoggy(e) {
// Call this extremely useful function on an <img>.
// The <img> will become a picture of a doggy.
e.target.setAttribute('src', 'https://s3.amazonaws.com/codecademy-content/courses/React/react_photo-puppy.jpeg');
e.target.setAttribute('alt', 'doggy');
}
const kitty = (
<img
src="https://s3.amazonaws.com/codecademy-content/courses/React/react_photo-kitty.jpg"
alt="kitty"
onClick={makeDoggy}
/>
);
ReactDOM.render(kitty, document.getElementById('app'));
The onClick attribute of const kitty is set to the function makeDoggy. To do this, you have to indicate you are using Javascript hence the {} brackets.However, the correct answer uses makeDoggy instead of using the standard function call: makeDoggy().
Also, the makedoggy function has an e parameter. When does that parameter get passed and how can a call to makeDoggy be made with a nonexsistent parameter when the function requires one?
Without parenthesis, you're not calling the function. The name of the function without the parenthesis is a reference to the function. Parentheses is not used in the function at that point because we are not calling the function at the point where the code is encountered, but instead want to pass a reference to the function. If you use makeDoggy() , the function will get called at that point, we instead want it to be called only after onClick, so we pass a reference to makeDoggy there.
Alternatively you can do onClick={(e)=>makeDoggy(e)}
e gets bound automatically using something called property initializer in es6.
If you want to pass parameters, you've to do something like onClick={(e)=>makeDoggy(e, "hello")}. This will pass "hello" as a second parameter to the function makeDoggy
No need for too much stress the solution is just double quote elimination "", in ReactJs to call a function inside an element you just have to do the following
onClick={functionName}
React can process function in curly braces.

Categories