TypeError: _this2 is undefined REACTJS - javascript

To quickly explain my problem, in my render, I call a function that displays each element of my array via the map function.
When I click on the button, I want to send the element to another function. But when I click on the button I have the following error: "TypeError: _this2 is undefined", here are some screenshots of my code:
Thank you in advance!

Function calls in JavaScript create their own this context by default. If you apply a traditional function to a map, it creates a unique this context for each iteration when the function is called. To prevent, you can either explicitly tell the function the this context to bind itself to, or you can use arrow functions, which automatically applies the current this context to the context created.
I've created an example below to illustrate the problem. In the List component, you can see that there is a renderList function that calls a map to iteratively render the items in the list. The below code won't work, as the map function creates a context in which the renderItem function is not defined:
class List extends Component {
constructor(props) {
super(props);
}
renderList(list) {
return (
<div>
{
list.map(function(item) {
return <div>{this.renderItem(item)}</div>
})
}
</div>
)
}
renderItem(item) {
return <div style={{color: 'green'}}>{item}</div>
}
render() {
return <div>
{
this.renderList(['one', 'two', 'three'])
}
</div>
}
}
To fix this, either bind it to the current context:
renderList(list) {
return (
<div>
{
list.map(function(item) {
return <div>{this.renderItem(item)}</div>
}.bind(this))
}
</div>
)
}
OR implicitly bind the current this context arrow functions:
renderList(list) {
return (
<div>
{
list.map(item => {
return <div>{this.renderItem(item)}</div>
})
}
</div>
)
}

Related

Does React bind this in setState callback?

I was expecting to see undefined being logged when the "Without binding" button was clicked because when you pass a method reference plainly as a callback, it shouldn't be called with the right this context, but with an arrow function, it should.
However, I saw that the callback function could access this and the value of this.state.number was logged properly. The method reference and arrow function performed the exact same. Why?
This does not have to do with arrow function class properties, it has to do with passing a reference to a method as a callback to setState as opposed to an arrow function.
class Hello extends React.Component {
constructor(props) {
super(props);
this.state = {
number: 1,
};
}
onClickWithThisBindingInCallback = () => {
this.setState({ number: 2 }, () => { this.myCallback(); });
};
onClickWithoutThisBindingInCallback = () => {
const myCb = this.myCallback;
this.setState({ number: 3 }, myCb);
};
myCallback() {
console.log(this.state.number);
}
render() {
return (
<div className="App">
<button onClick={this.onClickWithThisBindingInCallback}>With binding</button>
<button onClick={this.onClickWithoutThisBindingInCallback}>Without binding</button>
</div>
);
}
}
ReactDOM.render(
<Hello name="World" />,
document.getElementById('container')
);
<script src="https://unpkg.com/react#16.2.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom#16.2.0/umd/react-dom.development.js"></script>
<div id="container">
<!-- This element's contents will be replaced with your component. -->
</div>
React calls the callback function of setState with the component's instance this, as seen by this line of code.
Credits: #Li357
It is because you are given a lambda function to it:
onClickWithThisBinding = () => {
A lambda function is executed in it's given context. So the binding is actually onClick={() => { .. }}. That is why it has the this context.
This is due to the use of the arrow function.
Arrow functions always have the same this of their surrounding code.
See more here.
If you want the method not to be bound to that specific class you can use a normal function like this.
onClickWithoutThisBinding() {
const myCb = this.myCallback;
this.setState({ number: 3 }, myCb);
};

react add event listener base on condition

How to add attach event to jsx's element base on condition? The below example didn't do that, it simply pass a flag into the onClick function, didn't really attach the event.
const { hasSomething, name } = this.props
render(){
return(
<div onClick={()=>{hasSomething && this.fireSomething()}}>{name}/div>
)
}
I can duplicate 2 <div>, check if hasSomething exist then attach it to one of the element, but that's a bad duplication for me as {name} is declared twice.
how about:
render(){
return(
<div onClick={hasSomething && this.fireSomething}>{name}/div>
)
}
If hasSomething attach listener otherwise onClick will receive undefined just as you would not pass anything.
If above isn't something you are looking for you can also do something like this:
render(){
const props = {
//... some props
}
if(hasSomething) {
props.onClick = this.fireSomething;
}
return(
<div {...props}>{name}/div>
)
}
You create an object that holds every prop that should be passed to div and later you use spread operator to pass them.
Also remember to bind the function to this, if you need to reference props/state. I tend to do it in the construction i.e.
this.fireSomething = this.fireSomething.bind(this)
My approach is creating a new props object newProps that might or might not have an onClick property according to whether this.props has the required property.
In this example, if Foo does not received a bar prop, it won't create a new object with an onClick property.
class Foo extends Component {
handleBar() {
console.log(this.props.bar);
}
render() {
const newProps = this.props.bar
? {
...this.props,
onClick: this.handleBar.bind(this),
}
: this.props
return <div { ...newProps }/>
}
}
Here's a live example on CodePen
Wait, you just want to call a method if a condition is met? In that case you can just do this:
render() {
return(
<div onClick={() => {
if (hasSomething) {
this.fireSomething()
}
}}
)
}
or
fireSomething() {
if (hasSomething) {
// do logic
}
}
render() {
return(
<div onClick={() => this.fireSomething()}
)
}

React ref to component not exposing method

I'm using a ref to component to imperatively trigger a reset on a filter form from its parent.
In the same component we have:
handleFilterReset() {
// this.filterForm is defined but reset() isn't exposed
// see console.log(this.filterForm) output below
this.filterForm.reset()
}
render() {
return (
<FilterBox onReset={::this.handleFilterReset}>
<FilterForm ref={(ref) => { this.filterForm = ref }} />
</FilterBox>
)
}
And in FilterForm we have:
class FilterForm extends React.Component {
reset() {
// this is not being called
}
}
console.log output:
ProxyComponent {props: Object, context: Object, refs: Object, updater: Object, _reactInternalInstance: ReactCompositeComponentWrapper…}
It seems to me that everything is done according to the official docs. However, I get the following error:
Uncaught TypeError: this.filterForm.reset is not a function
at SalesChannelsList.handleFilterReset
Thanks
Found it ! It was "because" of React Intl.
1) Use the withRef option set to true when using injectIntl:
injectIntl(SalesChannelsFilterForm, { withRef: true })
2) In the ref callback of your component, you can access your instance with the following code
ref={(ref) => this.filterForm = ref.refs.wrappedInstance}
However this will crash because the ref callback is being called twice during the render(), the 1st time with a null value. So you should 1st verify that it has been defined. My complete solution:
In the render() method, on the component:
ref={::this.setFilterFormRef}
Then the handler:
setFilterFormRef(ref) {
if (ref && ref.refs) {
this.filterForm = ref.refs.wrappedInstance
}
}
Enjoy!
I would use ref="refName" instead of having a function (which is created again every render) and then access it through this.refs.
Anyway, here is a working example:
https://www.webpackbin.com/bins/-KjHtMcw3LcVEycggzWU

ReactJS - MouseClick gets triggered without a click

I'm new to React.JS and trying to create a click event on an element inside a rendered component.
Here is my code:
class InputPanel extends React.Component{
handleClick(i,j) {
this.props.dispatch(actions.someMethod());
// e.preventDefault();
}
render() {
const { dispatch, board } = this.props;
return(
<div>
{
board.map((row, i) => (
<div>{row.map((cell, j) => <div className="digit"
onClick={this.handleClick(i,j)}>{cell}</div>)}</div>
))
}
</div>
);
}
};
My problem is that "handleClick" gets triggered after page load without any mouse clicked!
I've read about React.JS lifecycle and thought about registering to click event in componentDidMount method, but i'm really not sure about it:
Is there any easier way ? (or: Am I doing something wrong that triggers click ?)
If adding componentDidMount method is the right way - how can I get the element I create in render method ?
You should not use .bind when passing the callback as a prop. There’s a ESLint rule for that. You can read more about how to pass callback without breaking React performance here.
Summary:
make sure you aren’t calling functions but pass functions as handlers in your props.
make sure you do not create functions on every render, for that, you need to bind your handlers in parent component, pass correct the required data (such as indices of iteration) down the child component and have it call the parent’s handler with the data it has
Ideally you’d create another component for the rows and pass the callback there. Moreover, ideally you’d bind the onClick in the parent component’s constructor (or componentWillMount). Otherwise every time render runs a new function is created (in both anonymous function handler () => { this.onClick() } and this.onClick.bind and defeat React’s vdom diff causing every row to rerender every time.
So:
class InputPanel extends React.Component{
constructor() {
super();
this.handleClick = this.handleClick.bind(this);
}
handleClick(i,j) {
this.props.dispatch(actions.someMethod());
// e.preventDefault();
}
render() {
const { dispatch, board } = this.props;
return(
<div>
{board.map((row, i) => <div>
{row.map((cell, j) => <Digit
onClick={this.handleClick})
i={i}
j={j}
cell={cell}
/>)}
</div>)}
</div>
);
}
};
class Digit extends React.Component {
constructor() {
super();
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.props.onClick(this.props.i, this.props.j);
}
render() {
return <div
className="digit"
onClick={this.handleClick}
>{this.props.cell}</div>
}
}
It is because you are calling this.handleClick() function instead of providing a function definition as onClick prop.
Try changing the div line like this:
<div className="digit" onClick={ () => this.handleClick(i,j) }>{cell}</div>
Also you have to bind this.handleClick() function. You can add a constructor and bind all the member functions of a class there. that's the best practice in ES6.
constructor(props, context) {
super(props, context);
this.handleClick = this.handleClick.bind(this);
}
You call this function in render. You should only transfer function and bind params.
onClick={this.handleClick.bind(null,i,j)}
You should use .bind().
class InputPanel extends React.Component{
handleClick(i,j) {
this.props.dispatch(actions.someMethod());
// e.preventDefault();
}
render() {
const { dispatch, board } = this.props;
return(
<div>
{
board.map((row, i) => (
<div>{row.map((cell, j) => <div className="digit"
onClick={this.handleClick.bind(null,i,j)}>{cell}</div>)}</div>
))
}
</div>
);
}
};

Why is my onClick being called on render? - React.js

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.

Categories

Resources