Setting onClick of dynamic elements generated through document.createelement - javascript

I am trying to set onClick function of dynamic generated elements. The function has to set state.
var root = document.getElementById("results_container");
var title = document.createElement('a');
title.setAttribute("id", 'title');
title.onclick = function () {
this.setState({
isOpen: !this.state.isOpen
});
}.bind(this)
I am getting the Uncaught TypeError: Cannot read property 'state' of undefined and I am assuming that onclick function is unable to reach this.state. Please help

You can use jQuery function on. It binds the action even in newly generated element.
$(document).on('click', '#test', function() {
// statement here
})
For your reference: jQuery .on()

Your this variable is undefined... If you are using react, you need to store the reference to the component instance (this) somewhere, and pass that to your bind function. This is probably a very poor way to do this, however. If you are using react, you likely want something more like this:
class Results extends Component {
constructor(props) {
super(props);
this.state = {
isOpen: false
};
}
render() {
return <div>
<a onClick={()=>this.setState({isOpen:!this.state.isOpen})}>
Title
</a>
{this.state.isOpen ? this.getOpenContent() : null}
</div>;
}
getOpenContent() {
return <div> ... </div>;
}
}

Related

ReactJS bind method to class component

Im doing ReactJS course in Codeacademny and they confused me.
(EDIT - full code) Photo of the code :
and there's no constructor or anywhere call to any bind method for the scream class method.
However in further exercises they tell you can't do that.
I probably miss something.
Apparently this.scream is an arrow function. Arrow function does not require binding. It points to the right context by default.
scream = () => { ... }
and there's no constructor or anywhere call to any bind method for the scream class method.
You only have to bind this to the component instance when the method actually uses this internally.
That's not the case in your example, so there is no need to bind it. No matter how the method is executed, it will always produce the same output.
Here is an example without React to demonstrate the difference:
var obj = {
value: 42,
method1() { // doesn't use `this`
console.log("yey!");
},
method2() { // uses `this`
console.log(this.value);
},
};
obj.method1(); // works
obj.method2(); // works
var m1 = obj.method1;
var m2 = obj.method2;
m1(); // works
m2(); // BROKEN!
var m2bound = obj.method2.bind(obj);
m2bound(); // works
scream = () => { ... }
render() {
return <button onClick={()=>this.scream()}>AAAAAH!</button>;
}
ou have to be careful about the meaning of this in JSX callbacks. In JavaScript, class methods are not bound by default. If you forget to bind this.handleClick and pass it to onClick, this will be undefined when the function is actually called.
This is not React-specific behavior; it is a part of how functions work in JavaScript. Generally, if you refer to a method without () after it, such as
onClick={this.handleClick}, you should bind that method.
When you define a component using an ES6 class, a common pattern is for an event handler to be a method on the class. For example, this Toggle component renders a button that lets the user toggle between “ON” and “OFF” states:
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// This binding is necessary to make `this` work in the callback
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(state => ({
isToggleOn: !state.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('root')
);```
You can simply use an arrow function (no need to bind in constructor).
scream = () => { console.log('Here') }
render() {
return <button onClick={this.scream}>AAAAAH!</button>;
}
Or you can call this function inline by.
render() {
return <button onClick={() => console.log('Here')}>AAAAAH!</button>;
}
You should use arrow functions for event handling to bind the function to the object. Other solution is to auto bind each function in the constructor like :
class Test{
constructor(){
Object.getOwnPropertyNames(Test.prototype).forEach(
method => this[method] = this[method].bind(this));
}
Read about #AutoBind decorator for more details.

How to send a ref to a function as a parameter in React Native?

I've imported a custom component into my screen and rendered it in the render() function. Then, created a ref to that custom component. Now, the render() function simply looks like this.
render() {
return (
<View>
<MyComponent ref={component => this.myComponent = component} />
</View>
)
}
Then, I've created another function to access the state of my custom component. I wrote it like this.
myFunction = (ref) => {
ref.setState({ myState: myValue })
}
Then, I called that function like this.
this.myFunction(this.myComponent)
But, it does not work. It gives me the following error.
null is not an object (evaluating 'ref.setState')
Actually what I need this myFunction to do is,
this.myComponent.setState({ myState: myValue })
Can you please help me to solve this problem?
ref is not your this object. it's dom for your componnet. For setState you need this of your component.
you can pass this as argument.
myFunction(this)
Now you will be able to do ref.setState in myFunction.
function myFunction(ref) {
ref.setState({ myState: myValue })
}
To use setState, just use your component's context (this keyword). The context also have your ref in it, so you don't need to pass it as an argument if you are inside one component(not forwarding down to children)
myFunction = (event) => {
this.myComponent // -> points to your ref, DOM element
this.setState() // use your setState like that
}
Don't forget to bind your context in parent component if you want to pass the handler to the child components. Refer to this useful topic
EDIT: Based on your comment, I guess you want to update the parent state by calling a handler in some other component. To do that, you need to create a handler in your parent component, bind the context and pass it as a property to the child component. Next up, you need to assign this handler in your child component. You cannot pass a context with setState method via argument or ref, this is just not how it works in javascript and in react.
Example:
// ParentComponent.js
class ParentComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
value: 1,
};
this.onChangeHandler = this.onChangeHandler.bind(this);
}
onChangeHandler(event) {
this.setState({
value: someNewValue // will update state on parent component
})
}
render() {
return (
<View>
<SomeComponent>{this.state.value}</SomeComponent>
<ChildrenComponent onChangeHandler={this.onChangeHandler} />
</View>
);
}
}
// ChildrenComponent.js
const ChildrenComponent = (props) => (
<View>
<Button
onPress={props.onChangeHandler}
title="click me to change parent state"
/>
</View>
);
Hopefully, this is what you need :)

React + Map + Button doesn't work [duplicate]

This question already has answers here:
React 0.13 class method undefined
(2 answers)
Uncaught ReferenceError: handleClick is not defined - React
(3 answers)
Closed 5 years ago.
Basic functionality.
Print a list DONE
Adding a button to each list DONE
Button call a particular function. NOW WORKING!!!
THANKS ALL OF YOU GUYS! -
30/10/2017 - I found solution. In the end of const renderItems, I just added a simple this and works. of course, I forgot in this sample to add this.handleClick = this.handleClick.bind(this); on constructor. So now, is working to me
I already did research about it, and the best solution that I found was here: But every time that I try to use this guide: https://reactjs.org/docs/handling-events.html
But I always get the error:
Uncaught TypeError: Cannot read property 'handleClick' of undefined
and I can't understand why. What I did (or doing) wrong?
import React, { Component } from 'react';
import axios from 'axios';
class myApp extends Component {
constructor(props) {
super(props);
this.state = {
repos: []
};
this.handleClick = this.handleClick.bind(this); // ADDED
}
componentDidMount() {
var $this = this;
var URL = JSON;
axios.get(URL).then(function(res) {
$this.setState({
repos: res.data
});
})
.catch(function(e) {
console.log("ERROR ", e);
});
}
handleClick() {
console.log('this is:', this);
}
render() {
const renderItems = this.state.repos.map(function(repo, i) {
return <li
key={i}>
<a onClick={(e) => this.handleClick(e)} >Click here!</a>
<span className='repoName'>
{repo.full_name}
</span>
<hr />
</li>
}, this); // just added THIS!
return (
<ul>
{renderItems}
</ul>
<section className='target'>
Target
</section>
);
}
}
export default myApp;
Your this inside of (e) => this.handleClick(e) is not class this. Just do it this way onClick={this.handleClick}.This way you will have click event inside this in handleClick function. If you want class this inside handleClick, than do it this.handleClick.bind(this)
You get an undefined error because you have a missing parameter e in your method definition. handleClick() without a parameter has a different identity than handleClick(e).
Bind handleClick in your constructor: this.handleClick = this.handleClick.bind(this);
Then change the onClick prop to onClick={this.handleClick}. Never use arrow functions inside the render function, this creates new identities of the function on every re-render which is bad practice and might cause performance issues as your application grows.
You can also use the experimental public class fields syntax, then you can define your click handler like so;
handleClick = (e) => {
// Stuff
}
Like this, you don't need to do any binding and you can just put this.handleClick in your onClick prop.

Props value not showing on top of render to a function ReactJS

However the this.props.NotesAll retrieving object from another component and it's showing object's to under render() method but when I'm trying to use that this.props.NotesAll on top of render on a function to working with those object, and i'm trying to check the value with console on functions it's just always say's undefined shit. So please help me ReactNinja's what actually is the wrong is going on here.
Here codes you can have a look on them
export default class EditNotes extends Component {
constructor(props) {
super(props);
this.state ={};
}
handleEdit() {
console.log(this + ' Clicked on That ');
}
//Here it's throwing error when I'm trying to click and console. the problem is here. i want this.props.NotesAll value here also to finding elements from objects
handleDelete(id) {
let Notes = this.props.NotesAll;
console.log(Notes)
}
render() {
let noteItems;
//this.props.NotesAll working fine here.
if (this.props.NotesAll) {
noteItems = this.props.NotesAll.map( Note => {
return(
<li key={Note.id}>{Note.body}
<button onClick={this.handleEdit.bind(Note.id)} className="btn btn-primary btn-sm">Edit</button>
<button onClick={this.handleDelete.bind(Note.id)} className="btn btn-danger btn-sm">Delete</button></li>
);
});
}
return(
<div className="col-md-4">
<h3 className="header-ttile">Current Notes:</h3>
<ul className="note-item-wrapper">
{noteItems}
</ul>
</div>
);
}
}
You define the binding in a wrong way, first parameter will be the context to which you want to bind.
Use this:
<button onClick={this.handleDelete.bind(this, Note.id)}
Syntax:
fun.bind(thisArg[, arg1[, arg2[, ...]]])
thisArg:
The value to be passed as the this parameter to the target function
when the bound function is called.
constructor(props) {
super(props);
this.state ={};
this.notes = props.notesAll;
this.handleDelete = this.handleDelete.bind(this);
}
And then try to access your this.notes inside your handeDelete function. I'm not sure because I'm not a react ninja neither, but I think it should work this way

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

Categories

Resources