0

I am listening for change on a file input, and I need to remove the listener after it has 'heard' something, each time.

The problem is that with a named function (can't remove listeners on anonymous functions) I lose context, and therefor cannot access state. Here's a basic version:

$ImgEl.on('change', () => {
  const reader = new FileReader();
    reader.onloadend = (e) => {
        // Do some stuff with state
        this.state.whatever;
    }
}

Utilizing this code with arrow functions, I maintain context and hence access to my state. However, if I go with a named function, I gain the ability to remove the listener, but I lose context.

Anyone else dealt with this already?

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
silencedogood
  • 3,209
  • 1
  • 11
  • 36
  • Which function do you want to remove? The change handler? – T.J. Crowder Jun 17 '19 at 17:14
  • I need to remove the listener callback function attached to the 'change' listener. – silencedogood Jun 17 '19 at 17:14
  • (Side note: It seems odd to be using what looks like jQuery with React.js...?) – T.J. Crowder Jun 17 '19 at 17:18
  • 1
    @T.J.Crowder I typically use jquery then refactor and utilize state for all UI changes. It's a noob thing, I'm growing out of it slowly. Let me review your answer with my app. I recall trying something similar and ran into context issues, but don't remember exactly what it was. Thanks. – silencedogood Jun 17 '19 at 17:21

1 Answers1

5

This has nothing to do with named vs. anonymous functions. What matters is whether you have a reference to the function.

If you want to remove the change handler, for instance:

// *** Create the function and remember a reference to it
const handler = () => {
  const reader = new FileReader();
    reader.onloadend = (e) => {
        // Do some stuff with state
        this.state.whatever;

        // Remove it
        $ImgEl.off('change', handler); // *** Remove the handler
    }
};
$ImgEl.on('change', handler); // *** Hook up the handler

It just so happens that that does create a named function, but even if it created an anonymous one, that would be fine because you'd have a reference to it.

You seem to be using jQuery, so I'll also just mention that with event namespaces, you wouldn't need a reference to the function to remove it, see the .foo in this:

$ImgEl.on('change.foo', () => {
  const reader = new FileReader();
    reader.onloadend = (e) => {
        // Do some stuff with state
        this.state.whatever;

        // Remove the handler
        $ImgEl.off('change.foo');
    }
});

I would use the version with the function reference, but you have options. :-)

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Thanks. But I noticed you removed reactjs from my tags. I'm probably missing something here, but my main issue isn't understanding the listener removal per se. The main issue is losing access to contextual react state, because this is all occurring within a react method handled on click. I'm going to edit my question in hopes to clarify. – silencedogood Jun 17 '19 at 17:30
  • @silencedogood - That's just [`this` management](http://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-context-inside-a-callback), nothing specific to React. :-) – T.J. Crowder Jun 17 '19 at 17:30
  • True enough. Works perfectly, I wasn't aware jquery extended the capability to add event namespaces. I was over complicating things, good job reigning me in. Thanks for being smart enough to make up for my dumbness :) – silencedogood Jun 17 '19 at 18:29