Расширение React Chrome — обмен сообщениями между фоном.js и реагирующий компонент не работают

#javascript #reactjs #google-chrome-extension

#javascript #reactjs #google-chrome-расширение

Вопрос:

В данный момент я изучаю React и хотел попробовать создать расширение Chrome с его помощью. К сожалению, я не могу заставить обмен сообщениями работать между моим компонентом и фоновым скриптом. Что я делаю не так? 🙂

Вот код, который должен обмениваться информацией между фоновым скриптом и компонентом React:

***** Реагирующий компонент *****

 import * as React from "react";
import { useState, useEffect } from "react";

import WatchListEntry from "./WatchListEntry";

const WatchList = () => {
  const [watchListEntries, setWatchListEntries] = useState<any>([]);

  useEffect(() => {
    chrome.runtime.onMessage.addListener((message) => {
      console.log(message);
      switch (message.type) {
        case "NEW_ARTICLE":
          setWatchListEntries([...watchListEntries, message.article]);
          console.log(message.data);
          break;
        default:
          break;
      }
    });
  }),
    [];

  return (
    <>
      <h1>Watchlist</h1>
      <ul>
        {watchListEntries.map((watchListEntry: any) => {
          <WatchListEntry data={watchListEntry} />;
        })}
      </ul>
    </>
  );
};

export default WatchList;
 

***** background.js *****

 import axios from "axios";

chrome.runtime.onInstalled.addListener(function () {
  chrome.contextMenus.create({
    id: "watchListMenu",
    title: "Libri Watchlist",
    contexts: ["page", "link"],
  });
  chrome.contextMenus.create({
    id: "addToWatchlist",
    parentId: "watchListMenu",
    title: "Test-Funktion-fuer-Links",
    contexts: ["page", "link"],
  });
});

chrome.contextMenus.onClicked.addListener((info) => {
  if (info.menuItemId === "addToWatchlist") {
    addToWatchlist(info);
  }
});

//Wie kann info für TypeScript verbessert werden? Erst einmal den Typ any gewählt.
const addToWatchlist = async (info: any) => {
  let articleId = getArticleId(info);
  let articleInfos = await getArticleInfos(articleId);
  let { ean, title, authorList } = articleInfos.result.articleAttributeView;
  /*   let ean = titleData.ean;
  let title = titleData.title;
  let author = titleData.authorList; */
  console.log(
    `console.log from addToWatchlist: ${ean}, ${title}, ${authorList}, ${articleId}`
  );
  chrome.runtime.sendMessage({
    type: "NEW_ARTICLE",
    article: { ean, title, authorList },
  });
};

const getArticleInfos = async (articleId: string) => {
  //Kann die Abfrage immer über chakryotik.buchhandlung.de geschehen? Oder müssen aufgrund unterschiedlicher Bestände die diversen Buchhändler abgefragt werden?
  try {
    const { data } = await axios.get(
      `https://...some API call...`
    );
    return data;
  } catch (error) {
    console.log(error);
  }
};

const getArticleId = (info: any) => {
  let url = info.linkUrl;
  if (url === undefined) {
    url = info.pageUrl;
  }
  let regExpForLink = /article/d /;
  let regExpForArticleId = /d /;
  let [match] = url.match(regExpForLink);
  let [articleId] = match.match(regExpForArticleId);
  return articleId;
};
 

***** manifest.json *****

 {
  "name": "Libri Watchlist",
  "description": "React Chrome Extension für Shopline",
  "manifest_version": 2,
  "version": "1.0.0",
  "icons": {
    "16": "watchlist.png",
    "48": "watchlist.png",
    "128": "watchlist.png"
  },
  "browser_action": {
    "default_icon": {
      "16": "watchlist.png",
      "48": "watchlist.png"
    },
    "default_popup": "popup.html"
  },
  "background": {
    "scripts": ["background.js"],
    "persistent": false
  },
  "content_scripts": [
    {
      "matches": ["*://*/*"],
      "js": ["content.js"]
    }
  ],
  "permissions": ["storage", "contextMenus", "https://*/"]
}
 

С консолью.войдите в функцию addToWatchlist, я вижу, что информация получена правильно. К сожалению, сообщение не получено в моем компоненте. Есть идеи? 🙂

Большое вам спасибо за вашу помощь!

Стефан

Комментарии:

1. Если код реакции находится во всплывающем окне browser_action (или page_action), то он запускается только тогда, когда отображается всплывающее окно, и не запускается, когда не отображается. В этом случае вы можете сохранить данные в chrome.storage.local или chrome.storage.sync и просто прочитать их в начале скрипта popup.

2. @wOxxOm Спасибо тебе! Я действительно не понимаю, что делают browser_action / page_action. Но я постараюсь решить свою проблему с помощью chrome.storage.local. 🙂

3. @wOxxOm Извините, что снова беспокою вас! Должен ли я в этом случае вызывать API из скрипта содержимого?

4. Похоже, мое предположение, возможно, было ошибочным. Чтобы избежать этого, вы всегда должны показывать свой manifest.json и объяснять, где выполняется каждый фрагмент кода. Для отправки сообщений в сценарии содержимого вы должны использовать chrome.tabs.SendMessage, см. Документацию .

5. Еще раз спасибо, @wOxxOm! Я только что добавил manifest.json в свой первый пост. Поскольку я не понимаю всего взаимодействия между фоном, контентом и остальным, мне трудно объяснить проблему. 🙂