We always use like this:
var MainComponent = React.createClass({
changeHandler() {
this.setState({
foo: 'bar';
})
},
render() {
return (<SubComponent onChange={this.changeHandler} />)
}
})
var SubComponent = React.createClass({
render() {
return (<button onClick={this.props.onChange}>Change</button>)
}
})
when we call this.props.onChange in SubComponent, we actually call changeHandler of MainComponent.
I suddenly realize that the context of changeHandler has been changed when pass to SubComponent using this.props, the this inside changeHandler should have been changed to this.props.
But as we all know, when we call changeHandler inside Subcomponent, the this in changeHandler is still MainComponent.
So I guess there may be some 'binding' when when pass function from MainComponent to SubComponent using this.props. The context of changeHandler is bound to MainComponent.
I add an console.log(this.props) in SubComponent's render, and I find some properties been add to this.props.onChange:
__reactBoundArguments: null
__reactBoundContext: point to Constructor MainComponent
__reactBoundMethod: point to function changeHandler
I think these are about the 'binding', but I don't know how they actually work.
Could someone please tell me something detail about this context binding, it's really nag me a lot. How does React do that?
When you define your components with React.createClass() there's a bit of auto-binding behind the scenes.
Your onChange={this.changeHander} effectively becomes onChange={this.changeHandler.bind(this)}. The reason for this is because it's generally what you want. This is documented here:
https://facebook.github.io/react/blog/2013/07/02/react-v0-4-autobind-by-default.html
Note however that if you define your components using the ES6 class syntax, this auto-binding does not occur. This was a deliberate decision to keep the behaviour the same as typical JavaScript classes. This is documented here:
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.
Related
This codepen toggles a button value from true to false.
I understand this apart from how this handleClick function is working:
handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}
Can someone please break this down and explain in simple terms how the function retrieves the isToggleOn bool value?
I know we can't directly use !this.state.isToggleOn in setState but can someone kindly explain in simple terms why this handleClick function is more reliable in this scenario for a React newbie?
This is where the handleClick function is called:
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
From the setState docs:
The first argument is an updater function with the signature:
(state, props) => stateChange
state is a reference to the component state at the time the change is being applied.
In your example prevState is state renamed, and it contains all of the assignments in state, including isToggleOn.
You could alternately just read this.state in the setState function. The prevState pattern is used to communicate that this is the old/current state, the state that is being changed.
setState docs
In this scenario you can actually use both, because it's really simple and you call the setState from the render function. In class components is a bit hard to find a place where this this.setState({oldState:this.state.oldState}) can be problematic.
On the contrary, if you use functional components or hooks, you can see this problem quite often.
JS is not Object oriented!
To understand this you have to think first that js is not an object oriented language. React tries just to simulate it. Basically when you change a state, the class containing it gets called again trying to run only the code which changes. In your case, when handleClick is called, the render function get triggered because the state has changed!
Said this, handleClick is not just a function! It's also a property of the class. React tries to understand whether it should "re-declare" those functions depending on the values they use.
Good Practice
In the case you wrote, isToggleOn: !prevState.isToggleOn, the function is indipendent. It doesn't need any other property of the class (apart of setState, which works with a different pattern), so after the state changes, the react engine doesn't have to set the function again.
Bad Practice (sometimes much much easyer to write)
On the contrary if you use isToggleOn: !this.state.isToggleOn the handleClick function is dependent of this.state so every time it changes, the react engine has to "re-declare" the function by sort of substituting this.state with {isToggleOn:...}
How to recreate that pattern
function myRandom(property){
//Kind of private Variable
let hiddenVar=Math.random();
return property(hiddenVar);
}
//Let's say here the Math class is unreachable while myRandom is.
myRandom((num)=>{
console.log(num);//This ac
})
Maybe just check the docs on this?
The second parameter to setState() is an optional callback function that will be executed once setState is completed and the component is re-rendered. Generally we recommend using componentDidUpdate() for such logic instead.
In essence, you are getting the previous instance of the state in the function, then making a change to the state and returning it. This new state will get saved and cause a re-render of your component.
If you use functional components, you can negate having to pass a callback here and could do something like:
function MyComponent() {
const [on, setOn] = React.useState(false)
return (
<button onClick={() => setOn(!on)}>
{on? 'ON' : 'OFF'}
</button>
);
}
In React's source code, the prototype function has a signature with three parameters:
function Component(props, context, updater) {
But everytime I see somebody extends React.Component using modern ES6 features, they declare constructor with only props as follows:
constructor(props)
What is the difference between a prototype function and constructor literal? And where do the rest two arguments go?
You can obviously use all of the three params provided in the Component. But in general, only in an advanced case we use props, not every time. Similarly, you can use others.
Here's an example with context api:
ES6 class component
class ContextConsumer extends React.Component {
/*
contexTypes is a required static property to declare
what you want from the context
*/
static contextTypes = {
currentUser: React.PropTypes.object
};
render() {
const {currentUser} = this.context;
return <div>{currentUser.name}</div>;
}
}
ES6 class component with an overwritten constructor
class ContextConsumer extends React.Component {
static contextTypes = {
currentUser: React.PropTypes.object
};
constructor(props, context) {
super(props, context);
...
}
render() {
const {currentUser} = this.context;
return <div>{currentUser.name}</div>;
}
}
Example taken from this blog. I will suggest you to look into the blog to be more familiar with it.
Another param is updater which you may have used this.forceUpdate() and doing so invoke the updater. But the fact, we do not use updater directly in normal case. Though, I have not faced such case to use the updater inside the constructor. You might be able to figure out if you face some advanced case.
To be more frank and to use react with clever, I never even try to use props as far as possible. They are just provided for us so that we can utilize in lifecycle hooks when needed.
Okay, let me explain it a little bit with react code:
function Component(props, context, updater) {
this.props = props;
this.context = context;
// If a component has string refs, we will assign a different object later.
this.refs = emptyObject;
// We initialize the default updater but the real one gets injected by the
// renderer.
this.updater = updater || ReactNoopUpdateQueue;
}
Component.prototype.forceUpdate = function(callback) {
this.updater.enqueueForceUpdate(this, callback, 'forceUpdate');
};
The Component function has 3 arguments which is being utilized inside the function. Later, its prototype forceUpdate is defined on which the updater is being hooked to enqueue the forceUpdate with enqueueForceUpdate. So, this.forceUpdate actually calling the Component updater and allows us to re-render the component. I hope, looking at its prototype method makes sense now.
What is the difference between a prototype function and constructor literal?
As far as I understand, you wanted to know why constructor is being called with the desired params.
The class/function constructor is used so that you can use an override to the function. For eg, passing props inside the constructor, you wanted to do an override with this. So, you explicitly notify the function to use the props as used inside the constructor.
So Es6 added the class keyword along with the constructor for it. It is however just syntactic sugar and is still based on the prototype model as before.
I don't know about the other two argos but I would guess it has to do with the function creating its own lexical scope.
This question already has answers here:
How to avoid bind or inline arrow functions inside render method
(4 answers)
Closed 4 years ago.
I am new to React and I have been told that when passing methods to the onClick handler you should not:
use inline arrow functions
call .bind(this, parameter)
As they both will create a new function on every single render, which has implications or performance
In my code I have a parent component sending a method (asideSelected()) as a prop to the child component. In the child component, I want to call this method with a parameter that my parent component receives. I have created the following solution:
Parent:
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
selected: ""
};
this.asideSelected = this.asideSelected.bind(this);
}
asideSelected(selected) {
this.setState({
selected: selected
});
}
render() {
return (
<Aside
selected={this.asideSelected}
/>
);
}
Child:
export default class Aside extends Component {
constructor(props) {
super(props);
this.selected = this.props.selected.bind(this);
this.showSelected = this.showSelected.bind(this);
}
showSelected(e) {
let selected = e.target.className;
this.selected(selected);
}
<div className="profile" onClick={this.showSelected} src={chat}></div>
}
This solution appears to be working, however, so does using inline arrow functions and binding inside of the onClick, I've never seen "bad" re-render and so I don't know if this is actually any different from the other ways of doing it. If it is unclear what I am attempting to do I am using the events target to pass as a parameter instead of doing it directly inside onClick. I am worried that this is a clunky or sub-par solution.
Any input welcome,
Thank you
The render is triggered by the setState().
Any time you update the state: this.setState(), the component and its children will re-render, you may read the doc here
It is unusual and unnecessary to bind to functions in the constructor of a react class. When you add a new function in the react object, for instance asideSelected(){ ... } in your example above, this function is bound to the prototype of the react object.
By adding this.asideSelected = this.asideSelected.bind(this); in your constructer, you create a new instance of asideSelected directly to the object. By doing this you add 2x the same functions.
Regarding the arrow functions, that is just ES6 syntax that auto scopes you code to this without the need to use .bind(this). This is just syntactical ES6 magic and should in theory not have any performance hit and makes your code look nicer.
Binding should be done in constructor and reason for it given in following link.I am not writing all blog here, because it's little bit lengthy. Let me know, if you don't understand it, then I will try to give more explanation.
Link: https://medium.freecodecamp.org/react-binding-patterns-5-approaches-for-handling-this-92c651b5af56
I'm following a tutorial to update states in ReactJS. I came across this line in the tutorial this.updateLanguage = this.updateLanguage.bind(this) and I don't understand what is going on. I understand the basics of this and bind, but I've never seen it done like this before. Can someone please explain? The full code:
var React = require('react');
class Popular extends React.Component {
// constructor to set default state
constructor (props) {
super(props);
this.state = {
selectLanguage: 'All'
};
// I don't understand this line
this.updateLanguage = this.updateLanguage.bind(this);
}
// updates state
updateLanguage(lang) {
this.setState(() => {
return {
selectLanguage: lang
}
});
}
render() {
var languages = ['All', 'JavaScript', 'Ruby', 'Java', 'CSS', 'Python'];
return (
<ul className='languages'>
{languages.map((lang) => {
return (
// adds listener to current state
<li style={lang === this.state.selectLanguage ? {color: '#d0021b'}: null}
onClick={this.updateLanguage.bind(null, lang)}
key={lang}>
{lang}
</li>
)
})}
</ul>
)
}
}
module.exports = Popular;
DOM callbacks such as click events will set the this context to the DOM element itself, in this case the li. Try removing the part you don't understand and see what happens - you'll see something like this.setState is not defined, because that function isn't defined in the context of the li element (it's basically looking for li.setState).
What bind is doing on that line is ensuring that whenever that function gets called, it will get called with the this context we want, in this case the Popular component - e.g. Popular.setState.
These days it's getting more and more common to see folks just using fat arrow syntax as a shorthand to preserve the this context - e.g. in this case onClick={ () => this.updateLanguage(lang) }.
(note for those concerned about performance: the fat arrow approach is cleaner but somewhat controversial since it's repeatedly declaring the function on every single render. That said, some folks claim there is minimal or no significant performance impact.)
If you not getting the bind(this) in constructor then its not but one of the way to avoid binding in render
Now why we need bind(this) in render let say we generally use
onChange={this.handleChange.bind(this)}
These approaches assume that you’re declaring React components using ES6 classes. If you use an ES6 class, React no longer autobinds.
So, this is the One way to resolve this is to call bind in render.
I have a lot of methods in my top-level React component that I want to use as callbacks in its children components. I understand that in ES6 I must manually bind the context of each method. My current constructor method looks something like this:
this.method1 = this.method1.bind(this);
this.method2 = this.method2.bind(this);
this.method3 = this.method3.bind(this);
...
This works; all of my children are able to retain the intended context whenever they invoke their callbacks but it seems like a lot of code to write for something I did not even need to write in ES5. Is there a quick way to bind context to all of my component methods without having to write all of this boilerplate?
I understand that in ES6 I must manually bind the context of each method.
Yeah, except that's not entirely true. ES6 allows you to express things a lot better than you could in ES5.
Writing your code in ES6 doesn't mean you directly translate the code you have from ES5. There's more idiomatic ways to do it using new features in current versions of React and features that are native to ES6.
import {Component} from 'react'
class Foo extends Component {
// this class doesn't even need constructor
createButton(text) {
// don't write
// return <button onclick={this.handleClick.bind(this)}>{text}</button>
// instead write
return <button onclick={e=> this.handleClick(e)}>{text}</button>
}
handleClick(event) {
console.log(event, 'button was clicked')
}
render() {
var {buttons} = this.props;
// don't write
// return <div>{buttons.map(this.createButton.bind(this)}</div>
// instead write
return <div>{buttons.map(this.createButton, this)}</div>
}
}
export default Foo;
// <Foo buttons={["one", "two", "three"]} />
Notice I used context in two different ways that didn't require Function.prototype.bind
Arrow functions have a lexical this therefore a binding isn't required in most scenarios. Arrow functions are new to ES6.
Array.prototype functions like map,reduce,forEach accept a thisArgument which allows you to change the context of the callback. This is not new to ES6, so there's nothing stopping you from using this in your ES5 code today.
But do you also see this is a stateless functional component? Stateless functional components are available as of React 0.14
In idiomatic React code, most of the components you write will be stateless, simply composing other components. We’re introducing a new, simpler syntax for these components where you can take props as an argument and return the element you want to render
source: React Blog v0.14
This code is functionally identical to the component above but requires no class or context ceremony
const createButton = (text) => {
return <button onClick={handleClick}>{text}</button>
}
const handleClick = (event) => {
console.log(event, 'button was clicked')
}
// stateless functional component
const Foo = ({buttons}) => {
return <div>{buttons.map(createButton)}</div>
}
export default Foo;
Of course this approach cannot work for components that involve state (or life cycle methods), but it works for any Components that just use props - which is most of your components.
It's just one more technique you have to write React apps in an idiomatic way that doesn't involve Function.prototype.bind.
For what it's worth, I haven't relied upon Function.prototype.bind (with code I've written) in years.
If you are using Babel, you can enable stage 0 and use the :: this binding operator.
You should be able to bind to the parent context when passing to the children:
method1() {
...
}
render() {
return <ChildComponent method1={::this.method1} />;
}
https://babeljs.io/docs/plugins/preset-stage-0/
http://babeljs.io/docs/plugins/transform-function-bind/
There are various valid approaches here; the one I prefer is to use the #autobind decorator:
import autobind from 'autobind-decorator';
class MyComponent extends React.Component {
#autobind
method1() {
// "this" is bound correctly
}
}
This requires the autobind-decorator module (or core-decorators, which exposes a similar function), plus babel-preset-decorators-legacy.