mcody
mcody

Reputation: 81

Chrome extension: Getting a variable from background.js to popup.js

I'm making my first chrome extension in React with the babel package that keeps track of your time on each webpage. I initiate the starting time in the background but need to access that start time in popup.js when they click on the popup. I need to figure out how to do this as the asynchronous nature of it all seems to be hindering me. Here are the relevant files:

manifest.json (I do use a persistent background since that seems like the best way to implement a timer despite the docs discouraging it's use.)

{
  "name": "Timer",
  "options_page": "options.html",
  "background": {
    "scripts": ["background.bundle.js"],
    "persistent": true
  },
  "browser_action": {
    "default_popup": "popup.html",
    "default_icon": "icon-34.png"
  },
  "permissions": ["tabs"],
  "icons": {
    "128": "icon-128.png"
  },
  "manifest_version": 2,
  "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"
}

popup.js:

import "../css/popup.css";
import Timer from "./popup/timer_component.js";
import React from "react";
import { render } from "react-dom";

const console = chrome.extension.getBackgroundPage().console;
let startingTime;

chrome.runtime.sendMessage({request: "getStartTime"}, function(response) {
    startingTime = response.done;
});

render(
  <Timer currentTimer = {startingTime}/>,
  window.document.getElementById("app-container")
);

background.js:

import '../img/icon-128.png'
import '../img/icon-34.png'

const console = chrome.extension.getBackgroundPage().console;
let startTime = Date.now();

chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
    if (message.request == "getStartTime") {
        sendResponse({done: startTime});
    }
});

The problem here is that the messages are asynchronous so startingTime is not getting updated in time for it to be passed to the render function. I want to know how do I get around this? Before trying message passing I tried acessing the variable directly with startingTime = chrome.extension.getBackgroundPage().startTime;, but this seems like it may be asynchronous as well, since startingTime is still undefined by the time it gets to the render function.

Any help or even just a point in the right direction would be greatly appreciated as I am running out of ideas for this roadblock.

Upvotes: 2

Views: 1610

Answers (1)

intentionally-left-nil
intentionally-left-nil

Reputation: 8284

You can change your popup.js to not call ReactDOM.render until it gets the data at needs from the background.

chrome.runtime.sendMessage({request: "getStartTime"}, function(response) {
    const startingTime = response.done;
    render(
      <Timer currentTimer = {startingTime}/>,
      window.document.getElementById("app-container")
    );
});

When I've done this for my extensions, I've noticed a chrome bug where the popup dimensions don't get set correctly. If that happens to you, you can set a width and height in the HTML

Upvotes: 2

Related Questions