How to Access React Instance (This) Inside Event Handler

Unable to access React instance (this) inside event handler

this.changeContent needs to be bound to the component instance via this.changeContent.bind(this) before being passed as the onChange prop, otherwise the this variable in the body of the function will not refer to the component instance but to window. See Function::bind.

When using React.createClass instead of ES6 classes, every non-lifecycle method defined on a component is automatically bound to the component instance. See Autobinding.

Be aware that binding a function creates a new function. You can either bind it directly in render, which means a new function will be created every time the component renders, or bind it in your constructor, which will only fire once.

constructor() {
this.changeContent = this.changeContent.bind(this);
}

vs

render() {
return <input onChange={this.changeContent.bind(this)} />;
}

Refs are set on the component instance and not on React.refs: you need to change React.refs.someref to this.refs.someref. You'll also need to bind the sendContent method to the component instance so that this refers to it.

How can I access React state in my eventHandler?

React state is asynchronous and it won't immediately guarantee you to give you the new state, as for your question Why can't I read markers if the original event starts at the map its an asynchronous nature and the fact that state values are used by functions based on their current closures and state updates will reflect in the next re-render by which the existing closures are not affected but new ones are created, this problem you wont face on class components as you have this instance in it, which has global scope.

As a developing a component , we should make sure the components are controlled from where you are invoking it, instead of function closures dealing with state , it will re-render every time state changes . Your solution is viable you should pass a value whatever event or action you pass to a function, when its required.

Edit:- its Simple just pass params or deps to useEffect and wrap your callback inside, for your case it would be

useEffect(() => {
map.current = Leaflet.map('mapid').setView([46.378333, 13.836667], 12)
.
.
.
map.current.on('click',()=> onMapClick(markers)) //pass latest change
}, [markers] // when your state changes it will call this again

for more info check this one out https://dmitripavlutin.com/react-hooks-stale-closures/ , it will help you for longer term !!!

Value of this in React event handler

This is correct behavior for JavaScript and React if you use the new class syntax.

The autobinding feature does not apply to ES6 classes in v0.13.0.

So you'll need to use:

 <button onClick={this.handleClick.bind(this)}>Click</button>

Or one of the other tricks:

export default class Observer extends React.Component {
constructor() {
super();
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
/* ... */
}
render() {
return <button onClick={this.handleClick}>Click</button>
}
}

React: Event handlers inside or outside functional component?

Concise answer: "outside whenever practical"

Keep reading for why...


In this answer, I ignore code style and source code module management (which are opinions).

Some important concepts to understand as you read this answer are the differences between a pure function, a closure, and an "impure" function (all the functions which don't fall into the other two categories). This has already been covered extensively on Stack Overflow, so I will not reiterate here.


Besides your observation about the nature of closures, the effects on reference equality (object identity) are very different. Consider the following:

In the code below (you can imagine it's a module file named component.jsx), the callback function is created at the top level of the module, outside the component. It is initialized once when the program runs and its value never changes for the lifetime of the JS memory:

const handleClick = ev => {/*...*/};

const Component = () => {
return <div onClick={handleClick}></div>;
};

In contrast, the code below shows the callback function being created inside the component. Because components themselves are just functions, it means that every time the component is invoked by React, the callback function is recreated (a completely new function, not equal to "the version of itself" from the previous render):

const Component = () => {
const handleClick = ev => {/*...*/};
return <div onClick={handleClick}></div>;
};

In a scenario like the above, where the function is used as an event handler callback directly on a child ReactElement, it won't make an observable difference. However, when passing a function to a child component or using it in a callback function to the useEffect hook, things become more complicated:

import {useEffect} from 'react';

const handleClick = ev => {/*...*/};

const Component = () => {
useEffect(() => {
const message = `The name of the function is ${
handleClick.name
}, and this message will only appear in the console when this component first mounts`;
console.log(message);
}, []);

return <div onClick={handleClick}></div>;
};

In the above example, the function doesn't need to be included in the effect's dependency list because its value cannot and will never change. It wasn't created inside the component and wasn't received from props, so the reference will be stable.

Conversely, consider this example:

import {useEffect} from 'react';

const Component = () => {
const handleClick = ev => {/*...*/};

useEffect(() => {
const message = `The name of the function is ${
handleClick.name
}, and this message will appear in the console EVERY time this component renders`;
console.log(message);
}, [handleClick]);

return <div onClick={handleClick}></div>;
};

In the code above, the function is recreated every time the component is invoked during render, resulting in the effect detecting the different value in the dependency array and running the effect again. It is required to include the function in the dependency array for this very reason.

The same concept applies when passing a function to child components as props. When a component receives a function as a prop value (a prop value is just the value of a property on an object argument to the function component), it can't know anything about the reference stability of the function, so that function must always be included in dependency lists where it's used.

This leads toward the concept of memoization, and related built-in hooks (e.g. useMemo, useCallback). (Similar to types of functions, memoization is a bigger topic and it has already been covered on SO and many other places.)

I'll give a practical example of how to create stable object identity for a closure function before ending this answer:

import {useCallback, useState} from 'react';

const Component = () => {
const [count, setCount] = useState(0);

const adjustCount = useCallback(
(amount) => setCount(count => count + amount),
[setCount],
// ^^^^^^^^
); // It's optional to include the "setState" function provided by `useState`,
// in the dependency array here (it's a special case exception because React
// already guarantees that the "setState" function it gives you will remain
// stable). However, it doesn't hurt to include it (although you might
// choose to omit it if you're working on a refactor toward
// performance micro-optimizations).

// Now, when you pass that function to a child component as a prop value,
// the object identity won't change on subsequent renders:
// vvvvvvvvvvv
return <SomeChildComponent adjustCount={adjustCount} />;
};

How does one access a class instance's `this` context from within an event handler without using `bind`?

In case of an instance method (own or prototypal) being used as event handler without explicit this binding one has to implement such a handler as arrow function in order to directly access the instantiation time's (enclosed) this context.

class A_Test {
constructor(a, b) {
this.selector = '.foam-types';
}
registerFoamTypeRadios() {
$(this.selector).on('click', '[name="foam-type"]', this.selectFoamType);
// mouseenter: this.showFoamTypeExample,
// mouseleave: this.hideFoamTypeExample,
}
selectFoamType = (evt) => {
const elm = evt.currentTarget;
const srcElm = evt.target;
console.log({ this: this, className: this.constructor.name, elm, srcElm });
}
showFoamTypeExample = (evt) => {}
hideFoamTypeExample = (evt) => {}
}
var theTest = new A_Test();

theTest.registerFoamTypeRadios();
* { margin: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<fieldset class="foam-types">
<legend>Foam Types</legend>

<label class="foam-type-option">
<input type="radio" name="foam-type" value="expanding"/>
<span>Expanding Foam</span>
</label>
<label class="foam-type-option">
<input type="radio" name="foam-type" value="shaving"/>
<span>Shaving Foam</span>
</label>
</fieldset>

Unable to access `this.state` inside event handler function: ReactJS

Because you forgot to bind the method removeComment in Board component, use this line:

removeComment={this.removeComment.bind(this)}

Use this in Board component:

<div className="board">
{
this.state.comments.map((text,i) => {
return (
<Comment key ={i} index = {i} commentText={text} removeComment={this.removeComment.bind(this)}/>
)
})
}
</div>

How to access DOM event-handlers for JSX-components in server-sided React

After a lot of messing around I came up with a solution that works quite well.

If I create my own instance of the ReactElement I want to render (in the example ViewElement(props)), I can then render the element using it's standard render-function:

let element = ViewElement(props);
let instance = new element.type();
let render = instance.render();

From here I can go through all the props for this element, so, say, onClick-handlers would be in render.props.

So what I do is to check each prop if the key matches a react-event-name (ex. onClick, onDragEnd, onDragEnter etc). If it does, and the value of this property is of type function - I have the event-name and it's handler-function:

Object.keys(render.props).map((key) => {
if (bigArrayOfAllTheEventNames.indexOf(key) !== -1) {
item.events[key] = render.props[key];//check if type is function.
}
});

Then I also iterate through the render.props.children recursivly to reach all it's child components and add every component which has events to an array.

The only problem left was that I needed a way to bind the rendered DOM-string to the javascript handlers I now have. For this I added a need to use a custom DOM-attribute, which then can be used to ID the component with something like this

$("[data-id=value]").on({event-name}, {it's JS-handler}).

It might not be perfect yet, but I think that this is the best solution out there.

Access state from Event Handler created within React.js UseEffect Hook

Your event listener registers a function (reference) which has count as 0 in the environment it is defined and when a new render happens, your reference is not being updated which is registered with that element and that registered function reference still knows that count is 0 even though count has been changed but that updated function was not registered which knows the updated value in its context. So you need to update event listener with new function reference.

useEffect(() => {
const target = subtitleEl.current;
target.addEventListener("click", onSubtitleClick);

return () => {
console.log("removeEventListener");
target.removeEventListener("click", onSubtitleClick);
};
}, [onSubtitleClick]);

However, you don't need that messy code to achieve what you are doing now or similar stuff. You can simply call that passed function on click and don't attach to element through ref but directly in jsx.

<div
className="panelText"
style={{ fontSize: "13px" }}
onClick={onSubtitleClick}
ref={subtitleEl}
>
Button2
</div>

Get reference to React component in event handler

I think I understand the question vbarbarosh is asking, or at least I had a similar one that led me to this post. So if this doesn't answer the original question hopefully it can help others who land here.

In my case I have a React component with n number of children for defining configuration options for a UI action. Each child has a different ref identifying what config option the input represents and I want to be able to directly access the ref so I can then call methods exposed on my child component. (I could expose data attrs and use jQuery to extract, but that seems like a lot of extra hoops & performance issues)

My first attempt was this:

...
<Config ref="showDetails" onChange={this.handleChange} />
<Config ref="showAvatar" onChange={this.handleChange} />
...

Ideally, I wanted to bind all the change events to a single handler, then extract the ref from the target that dispatched the event. Unfortunately the dispatched SyntheticEvent does not provide a way to get the ref of the target so I can't make a direct call to this.ref[name].methodIWantToCall().

What I did find was an article in the React docs that lead me to a solution:

https://facebook.github.io/react/tips/communicate-between-components.html

What we can do is take advantage of JavaScript binding and pass in additional arguments.

...
<Config ref="showDetails" onChange={this.handleChange.bind(this, 'showDetails')} />
...

Now in my handler I get the addition data and can access my refs:

handleChange: function(refName, event) {
this.refs[refName].myMethodIWantToCall()
}

The trick is that when binding, the argument order is changed and the first argument is now the bound value passed in and the event is now the second argument. Hope that helps!



Related Topics



Leave a reply



Submit