I am familiar with Javascript function bind. But I don't understand why in following React.js snippet is this bind again to this. Has is something common with constructor, because this in constructor can have different values depending on usage?
Thank you in advance for replies
class QuotesLibrary extends React.Component {
constructor(props) {
super(props);
this.search = debounce(this.search.bind(this), 300);
}
search(searchTerm) {
this.props.relay.setVariables({searchTerm});
}
render() {
return (
<div className="quotes-library">
<SearchForm searchAction={this.search} />
<div className="quotes-list">
{this.props.library.quotesConnection.edges.map(edge =>
<Quote key={edge.node.id} quote={edge.node} />
)}
</div>
</div>
)
}
}
What this.search.bind(this) does it that it is binding the key this inside to the function to the context of your React Component and what it basically means is that whenever you try to access a property of the React Component, you can access it like this.props since this will then refer to the React Component's context and not the function itself.
The significance of this.search before bind is that it is trying to access the function search which is in the context of the React Component and hence you are only binding it once and not twice.
I hope I was able to explain the situation properly
You shouldn't use Function.bind(this) : you should use arrow function. Arrow functions are bind to the class (so to the component).
class QuotesLibrary extends React.Component {
constructor(props) {
super(props);
this.search = debounce(this.search, 300);
}
search = (searchTerm) => {
this.props.relay.setVariables({searchTerm});
}
render() {
return (
<div className="quotes-library">
<SearchForm searchAction={this.search} />
<div className="quotes-list">
{this.props.library.quotesConnection.edges.map(edge =>
<Quote key={edge.node.id} quote={edge.node} />
)}
</div>
</div>
)
}
}
Here's an example of how the difference works -
As you can see, the first call will log 'undefined' and the second one will log 'Bar', because the 1st call wasn't binded, and calling functions indirectly (as promise results or as callbacks) doesn't keep the reference to this when it runs - bind tells it what its this is referring to.
function debounce(fn, to) {
setTimeout(fn)
}
class Foo {
constructor () {
this.fullName = 'Bar'
}
speak () {
console.log("My name is", this.fullName)
}
test () {
debounce(this.speak, 1000) // undefined
debounce(this.speak.bind(this), 2000) // "Bar"
}
}
let foo = new Foo()
foo.test()
Why are you saying "again"? You only bind it once, not twice.
debounce from _underscores library takes a function and returns another, therefore to get the this context in the search function you need to bind it to the search.
It's the exact same as binding functions normally in the constructor.
Related
I have a component that I have created:
class Create extends Component {
constructor(props) {
super(props);
}
render() {
var playlistDOM = this.renderPlaylists(this.props.playlists);
return (
<div>
{playlistDOM}
</div>
)
}
activatePlaylist(playlistId) {
debugger;
}
renderPlaylists(playlists) {
return playlists.map(playlist => {
return <div key={playlist.playlist_id} onClick={this.activatePlaylist(playlist.playlist_id)}>{playlist.playlist_name}</div>
});
}
}
function mapStateToProps(state) {
return {
playlists: state.playlists
}
}
export default connect(mapStateToProps)(Create);
When I render this page, activatePlaylist is called for each playlist in my map. If I bind activatePlaylist like:
activatePlaylist.bind(this, playlist.playlist_id)
I can also use an anonymous function:
onClick={() => this.activatePlaylist(playlist.playlist_id)}
then it works as expected. Why does this happen?
You need pass to onClick reference to function, when you do like this activatePlaylist( .. ) you call function and pass to onClick value that returned from activatePlaylist. You can use one of these three options:
1. using .bind
activatePlaylist.bind(this, playlist.playlist_id)
2. using arrow function
onClick={ () => this.activatePlaylist(playlist.playlist_id) }
3. or return function from activatePlaylist
activatePlaylist(playlistId) {
return function () {
// you code
}
}
I know this post is a few years old already, but just to reference the latest React tutorial/documentation about this common mistake (I made it too) from https://reactjs.org/tutorial/tutorial.html:
Note
To save typing and avoid the confusing behavior of this, we will use
the arrow function syntax for event handlers here and further below:
class Square extends React.Component {
render() {
return (
<button className="square" onClick={() => alert('click')}>
{this.props.value}
</button>
);
}
}
Notice how with onClick={() => alert('click')}, we’re passing a
function as the onClick prop. React will only call this function after
a click. Forgetting () => and writing onClick={alert('click')} is a
common mistake, and would fire the alert every time the component
re-renders.
This behaviour was documented when React announced the release of class based components.
https://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html
Autobinding
React.createClass has a built-in magic feature that bound all methods to this automatically for you. This can be a little confusing for JavaScript developers that are not used to this feature in other classes, or it can be confusing when they move from React to other classes.
Therefore we decided not to have this built-in into React's class model. You can still explicitly prebind methods in your constructor if you want.
import React from 'react';
import { Page ,Navbar, Popup} from 'framework7-react';
class AssignmentDashboard extends React.Component {
constructor(props) {
super(props);
this.state = {
}
onSelectList=(ProjectId)=>{
return(
console.log(ProjectId,"projectid")
)
}
render() {
return (
<li key={index} onClick={()=> this.onSelectList(item.ProjectId)}></li>
)}
The way you passing the method this.activatePlaylist(playlist.playlist_id), will call the method immediately. You should pass the reference of the method to the onClick event. Follow one of the below-mentioned implementation to resolve your problem.
1.
onClick={this.activatePlaylist.bind(this,playlist.playlist_id)}
Here bind property is used to create a reference of the this.activatePlaylist method by passing this context and argument playlist.playlist_id
2.
onClick={ (event) => { this.activatePlaylist.(playlist.playlist_id)}}
This will attach a function to the onClick event which will get triggered on user click action only. When this code exectues the this.activatePlaylist method will be called.
In this component, I'm not able to call a function in the render method by going this.functionName if it's not an arrow function. Howevever, I am able to call this.setState effectively in both an arrow function and a regular function. Why is "this" different in some situations, but seemingly the same in other situations in a React component like this?
import React from 'react';
class Address extends React.Component {
state = {
fullAddress: "5001"
}
componentDidMount() {
this.setState({
fullAddress: "hello"
})
}
hello = () => {
this.setState({
fullAddress: "hello1"
})
}
logMessage() {
console.log(this.state.fullAddress);
}
render() {
return (
<div className="address">
{this.state.fullAddress}
<input type="button" value="Log" onClick={this.hello} />
</div>
);
}
}
export default Address;
In your example, logMessage will probably break since you need to specify your this context to it.
In this case, simply bind it in Address's constructor like so:
class Address extends Component {
constructor(props) {
super(props)
this.logMessage = this.logMessage.bind(this)
}
}
A second approach would be the same you already used with hello as arrow function like. Arrow functions keep your current context (this) and that's why you have access to this.setState inside hello's body for example.
I'm trying to follow the suggestion in this react-eslint doc to avoid using inline functions.
I have a div with an onClick funciton like so:
onClick={ () => this.props.handleClick(some_constant) }
This works perfectly fine, however I don't want to have an inline function. When I try to abstract it by following the pattern in the provided link above, I get a setState error that runs infinitely.
class Foo extends React.Component {
constructor() {
super();
this._handleClickWrapper = this.handleClickWrapper.bind(this);
}
_handleClickWrapper() {
// handleClick is a callback passed down from the parent component
this.props.handleClick(some_constant)
}
render() {
return (
<div onClick={this._handleClickWrapper}>
Hello!
</div>
);
}
}
What needs to be done so that I can avoid using inline functions?
Edit:
I made a serious typo, but in my code, I have what is currently reflected and it is still causing the error.
You bound the wrong function to this. It should be:
this._handleClickWrapper = this._handleClickWrapper.bind(this);
This way _handleClickWrapper will always be bound to the context of the component.
If you really really really want to follow the jsx-no-bind rule, you can create a new component and pass someConstant in as a prop. Then the component can call your callback with the value of someConstant:
class FooDiv extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
render() {
return <div onClick={this.handleClick}>Hello!</div>
}
handleClick() {
this.props.onClick(this.props.someConstant);
}
}
Then your Foo component can just do this:
class Foo extends React.Component {
render() {
const someConstant = ...;
return (
<FooDiv
onClick={this.props.handleClick}
someConstant={someConstant}
/>
);
}
}
Having said that, I would recommend not following jsx-no-bind and just use bind or arrow functions in render. If you're worried about performance due to re-renderings caused by using inline functions, check out the reflective-bind library.
There is a typo
this._handleClickWrapper = this.handleClickWrapper.bind(this);
should be
this._handleClickWrapper = this._handleClickWrapper.bind(this);
in your constructor you forgot to pass props to super()
constructor(props) {
super(props);
this._handleClickWrapper = this._handleClickWrapper.bind(this);
}
Tipp: You can avoid binding (and even the constructor) by using arrow functions declaration inside the class (babel-preset-es2016).
class Foo extends React.Component {
state = {} // if you need it..
onClick = () => {
this.props.handleClick(some_constant)
}
render() {
return (
<div onClick={this.onClick}>
Hello!
</div>
);
}
}
This way you components gets smaller, and easier to read.
https://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html#autobinding
There are two component in react project.
1, Parent
2, Child
Now, I'd like to use childMethod in Parent component.
In some pages of stackoverflow, everyone said refs is effective.
But in my project, it's not working.
class Parent extends Component {
parentMethod(){
this.refs.child.childMethod();
}
render() {
return (
<Child ref='child'/>
);
}
}
class Child extends Component {
childMethod() {
alert('You made it!');
}
render() {
return (
<h1 ref="hello">Hello</h1>
);
}
}
When I use above code, there is one error code in browser console.
_this3.refs.child.childMethod is not a function
I'd like to use child method, so I have 2 questions.
1, What's "_this3" ? How can I use refs correctly?
2, Do you have any other idea about it?
class Parent extends React.Component {
constructor(props) {
super(props);
// binding methods to the class so they don't lose 'this'
// when invoked from another environment.
this.parentMethod = this.parentMethod.bind(this);
this.setChildRef = this.setChildRef.bind(this);
}
parentMethod() {
this.childNode.childMethod();
}
// intentionally avoided using an arrow fuction inside JSX
// for we don't want a new anonymous fn created on every render.
setChildRef(node) { // receives reference to component as argument
this.childNode = node;
}
render() {
return (
<div>
<Child ref={this.setChildRef}/>
<button onClick={this.parentMethod}>Parent Button - Click me :)</button>
</div>
);
}
}
class Child extends React.Component {
childMethod() {
alert('You made it!');
}
render() {
return (
<h1>Child</h1>
);
}
}
Working fiddle: https://jsfiddle.net/free_soul/9vrLrw8h/
What's "_this3"?
Probably a variable that you may see in browser while debugging. It just represents an execution context.
How can I use refs correctly?
It is preferred to treat the ref as a callback attribute and no longer depend on the refs Object. If you do use the refs Object, avoid
accessing refs of descendant components. You should treat refs as a
private accessor and not part of a component's API. Treat only the
methods exposed on a component instance as its public API.
I have a React Component such as :
function callback(params){..
// I need to use this.setstate but this callback function is called
// from other component. How do I bind value of this here
// 'this' of RespProperties
...
}
class RespProperties extends Component { ..
...
}
This callback function is called from some other component. How do I bind value of 'this' here so that it can use states of this component?
I don't really understand the question.
I don't know if this is what you mean, but if you want to save the 'this' temporary variable, then just create a global array or single variable to store the 'this'.
var thisTemp;
function callback(params){..
// use variable here
thisTemp.blah();
...
}
class RespProperties extends Component { ..
//Assign this to thisTemp
thisTemp = this;
...
}
You could separate this shared function, leaving it outside the components, then use bind:
function callback(params){
this.setState({ works: true });
}
class RespProperties extends Component {
state = { works: false }
...
render = () => <button onClick={callback.bind(this)}>Click</button>
// ^ here we use .bind(this) to... well...
// bind `this` so we can use it in the function xD
}
class SomeOtherComponent extends Component {
state = { works: false }
...
render = () => <button onClick={callback.bind(this)}>I'm from some other component</button>
}