buydadip
buydadip

Reputation: 9417

How to use react setState with chrome API

I want to use react's setState with chrome API but I'm running into an issue...

componentDidMount() {

    chrome.runtime.onMessage.addListener(function(request, sender) {
        if (request.action == "getSource") {
            this.setState({sourceCode: request.source});
        }
    }); 
}

I tried the following but chrome API does not recognize setState as a function, so then I tried to first save request.source as a variable...

componentDidMount() {
    var source = "";
    chrome.runtime.onMessage.addListener(function(request, sender) {
        if (request.action == "getSource") {
            source = request.source;
        }
    });
    this.setState({sourceCode: source});
}

But when I try the following, source remains an empty string. I cannot figure out why since source is being set to request.source. How can I fix this?

EDIT

I am calling a script as so...

chrome.tabs.executeScript(null, {
        file: 'src/js/scripts/getPageSource.js'
     }, function() {
     ...

and inside the script I have the following...

chrome.runtime.sendMessage({
    action: "getSource",
    source: DOMtoString(document)
});

Where DOMtoString function simply returns a string. It is the caught by my componentDidMount which I have verified by printing to the console inside the if statement.

It has come to my attention that the addListener is asynchronous. Is there any way I can save the result in the state?

Upvotes: 3

Views: 1764

Answers (1)

intentionally-left-nil
intentionally-left-nil

Reputation: 8284

You need to bind this so it is unchanged in the event listener

chrome.runtime.onMessage.addListener(function(request, sender) {
    if (request.action == "getSource") {
        this.setState({sourceCode: request.source});
    }
}.bind(this));

Your second attempt doesn't work because the callback is asynchronous. You need to call setState when the callback returns. In your second attempt, you register for the listener but then immediately call setState.

Edit: Alternatively, you could switch to using arrow functions instead. This would lexically bind this so it would be unchanged.

chrome.runtime.onMessage.addListener((request, sender) => {
    if (request.action == "getSource") {
        this.setState({sourceCode: request.source});
    }
});

Upvotes: 3

Related Questions