Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save EduardoAC/5551f5228af5285d2dfca43092d02728 to your computer and use it in GitHub Desktop.
Save EduardoAC/5551f5228af5285d2dfca43092d02728 to your computer and use it in GitHub Desktop.
React Chrome Extension: Combining React Context with Runtime onMessage Listener to capture state updates via messages exchanged between content and background scripts in Manifest v3.
// Message and response are define in https://gist.github.com/EduardoAC/000b1e39a6ec10a892e7c6cd93730a53
interface GlobalContext {
review: number
language: string
setLanguage: Function
}
const globalContext = createContext<GlobalContext>({
review: -1
language: "en"
setLanguage: () => {}
})
interface GlobalContextProvider {
children: ReactNode
}
export function GlobalContextProvider({children}: GlobalContextProvider) {
const [review, setReview] = useState(-1)
const [language, setLanguageState] = useState("en")
const handleMessageListener = (message: Message<number | string>) => {
switch(message.type) {
case "review":
// Handle review, reviewHandler(message, setReview) | review = reviewHandler(message) -> state in the handler
break
case "language":
// For simplicity, assume only message language received by content script is the new language selection
setLanguageState(message.data)
break
default:
console.error("incorrect message") // Up to you how you handle the error case
break
}
}
useEffect(() => {
// Example fetching review data on context initialization
retriveReview().then((review: number) => {
setReview(review)
})
// ...
// Language and other data can be fetch together with review or separately on initialization
// ...
// Listening for background script message
chrome.runtime.onMessage.addListener(handleMessageListener)
return () => {
chrome.runtime.onMessage.removeListener(handleMessageListener)
}
}, [])
const context = {
review,
language,
setLanguage: (newLanguage: string) => {
sendMessage({ type: "language", subtype: "update", data: newLanguage})
setLanguageState(newLanguage) // Assuming that sendMessage always succes for simplicity
}
}
return <globalContext.Provider value={contextValue}>{children}</globalContext.Provider>
}
export const useGlobalContext = () => {
return useContext<GlobalContext>(globalContext)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment