Reputation: 3593
I just noticed, that if I define normal class component functions, I do not need to bind these anymore inside the class constructor... (so even if I dont use ES6 public class field syntax), I can just normally pass those functions to my event handlers via onClick={this.someFunction} without the need to bind them to my class beforehand and it does not throw me an error when the native DOM event (or synthetic event in React's case) is executed. And it also does not matter if I use an arrow function as my event handler or just pass the function reference...
is this a new feature to React? I think some months ago, this feature was not there yet..
EDIT: here is some code example, its a simple newsfeed api app, where index has a ListItem subcomponent thats passed the click handler...
import {React, Component, fetch, API_KEY, BASE_URL} from '../config/config';
import ListComponent from '../components/ListComponent';
import PropTypes from 'prop-types';
import { makeStyles } from '@material-ui/core/styles';
import ListItem from '@material-ui/core/ListItem';
import ListItemText from '@material-ui/core/ListItemText';
import { List } from '@material-ui/core';
const useStyles = makeStyles(theme => ({
root: {
width: '100%',
height: 400,
maxWidth: 360,
backgroundColor: theme.palette.background.paper,
},
}));
export default class index extends Component {
constructor(props) {
super(props);
this.state = {
news: this.props.news
}
}
static async getInitialProps() {
let querystring = `${BASE_URL}top-headlines?q=sex&fsortBy=popularity&apiKey=${API_KEY}`;
console.log(querystring);
let news = await fetch(querystring);
news = await news.json();
//console.log("NEWS:",news.articles);
return {
news: news.articles
}
}
getOutput (e) {
console.log("Item ",e," was clicked!");
}
render() {
return (
<div>
{
this.state.news.map((news,index) => (
// <ListItem button
// key={index}
// onClick={e => this.getOutput(e)}>
// <ListItemText primary={`${news.title}`} />
// </ListItem>
<ListComponent
index = {index}
news = {news}
clicked = {this.getOutput}
/>
)
)
}
</div>
)
}
}
Here is the List subcomponent:
import React from 'react'
export default function ListComponent({index,clicked,news}) {
return (
<li key={index} onClick ={clicked}>
{
news.title
}
</li>
)
}
I just tested it, and it worked! Note: This is a Next.js example, but I have tested it in a normal React-app (created with create-react-app), too and it worked with same kind of example... when I click a list item I get console output:
Item Class {dispatchConfig: {…}, _targetInst: FiberNode, nativeEvent: MouseEvent, type: "click", target: li, …} was clicked!
Upvotes: 1
Views: 2757
Reputation: 31024
This is not related to react
but how JavaScript's class
and this
works.
In your example you are not getting errors because you are not doing anything wrong. Although when you want to call this.setState
or reference anything via this
you may get an error or unexpected results because this
will not reference what you think it will, it will reference the element that triggered the event.
Why class field with arrow functions "solve" the problem without hard binding the this
? because they way they "handle" the this
context, which they actually don't do anything. meaning, what ever the this
reference in the wrapping execution context, that's the reference you will get inside an arrow function.
By the way, there is a difference between a class field functions and class methods is that class methods are created on the prototype and fields are created on the instance.
I've made a simple flow chart that may help understand what is this
referencing to for a given context (always top to bottom, order matters)
Upvotes: 1
Reputation: 584
This is not a new feature of React. You can access any function or property from within class without binding. The reason why you do binding( or declare arrow function) is to connect local this
to global context so it can refer to the class(parent function). Try using e.g this.props
inside getOutput function and you will get an error.
Upvotes: 1