- vừa được xem lúc

[ReactJS] Push notification sử dụng Firebase Cloud Messaging

0 0 25

Người đăng: Nguyễn Danh Khương

Theo Viblo Asia

Xin chào, trong bài viết này mình sẽ thực hiện chức năng push notification trên trang web ReactJS sử dụng Firebase Cloud Messaging (FCM)

Các bước chính

  1. Khởi tạo project ReactJS
  2. Tạo project Firebase và setup FCM
  3. Cấu hình Firebase trong app ReactJS để nhận message push từ FCM
    a. Foreground
    b. Background

1. Khởi tạo project ReactJS

Để khởi tạo project ReactJS đơn giản, mình sử dụng create-react-app:

npx create-react-app demo-fcm --template typescript

Sau đó chạy thử project:

cd demo-fcm
npm start

Kết quả:

2. Tạo project Firebase và setup FCM

Đăng nhập vào Firebase Console, chọn Add project:

Mình đặt tên là demo-fcm, chọn ContinueCreate project

Đợt 1 chút để project được khởi tạo xong, chọn Continue.
Tại trang chủ của project, bấm vào biểu tượng < /> để setup cho Web

Mình đặt tên là demo-fcm-app, chọn** Register app**

Chọn Continue to console
Tại màn hình chính của project, ở menu bên trái, nhấn vào biểu tượng răng cưa, chọn Project settings. Sau đó chọn tab Cloud Messaging

Ở phần Cloud Messaging API (Legacy) (đang hiện Disable), chọn biểu tượng 3 chấm => Manage API in Google Cloud Console
Ở cửa sổ mở ra, chọn Enable:

Sau đó reload lại trang Project settings, phần Cloud Messaging API (Legacy) đã được Enabled và bên dưới là Server key
Tại phần Web Push certificates, bấm vào Generate key pair: (cái này là VAPID key)

Như vậy là đã cấu hình setup xong project Firebase

3. Cấu hình Firebase trong app ReactJS để nhận message push từ FCM

Trước tiên mình sẽ install package firebase, ở đây mình dùng firebase version 8:

npm install _@.com

Tạo file constants.ts trong thư mục src để lưu Firebase config:

//src/constants.ts
export const firebaseConfig = { apiKey: process.env.REACT_APP_FIREBASE_API_KEY, authDomain: "your_auth_domain", projectId: "your_projectId", storageBucket: "your_storage_bucket", messagingSenderId: "your_messaging_sender_id", appId: process.env.REACT_APP_FIREBASE_APP_ID
};

Config lấy từ Project settings, tab General:

a. Foreground

Để nhận foreground message (khi đang ở tab trang web), mình sẽ viết 1 hàm lắng nghe message khi đang focus vào web.
Trong thư mục src, tạo file firebase.ts với nội dung:

import { useEffect } from 'react';
import firebase from "firebase/app";
import "firebase/messaging";
import { firebaseConfig } from './constants'; if (!firebase.apps.length) { firebase.initializeApp(firebaseConfig);
} else { firebase.app(); // if already initialized, use that one
} let messaging: firebase.messaging.Messaging; if (typeof window !== "undefined") { if (firebase.messaging.isSupported()) { messaging = firebase.messaging(); }
} export const getMessagingToken = async () => { let currentToken = ""; if (!messaging) return; try { currentToken = await messaging.getToken({ vapidKey: process.env.REACT_APP_FIREBASE_FCM_VAPID_KEY, }); console.log("FCM registration token", currentToken); } catch (error) { console.log("An error occurred while retrieving token. ", error); } return currentToken;
}; export const onMessageListener = () => new Promise((resolve) => { messaging.onMessage((payload) => { resolve(payload); }); });

File này mình định nghĩa hàm onMessageListener để hứng message, hàm này có thể được gọi trong useEffect:
Trong file App.tsx, mình thêm 2 useEffect sau:

useEffect(() => { getMessagingToken(); },[]) useEffect(() => { onMessageListener().then(data => { console.log("Receive foreground: ",data) })
})

useEffect đầu tiên dùng để lấy Registration token từ Firebase
useEffect sau dùng để hứng message được push từ Firebase (lưu ý là useEffect này không có dependencies)
Chạy thử project lên xem nhé:
Trang web sẽ yêu cầu cho phép gửi thông báo, chọn Cho phép, ta sẽ thấy FCM registration token được console.log ra:

Thử bắn message từ firebase (lưu ý là phải đang mở tab của trang web):
Vào Firebase, tại menu bên trái, chọn Engage => Cloud Messaging => Send your first message:

Chọn Send test message, paste token được console.log ra ở trên và chọn +

Chọn Test và message được bắn về trang web:

Như vậy là chức năng push notification foreground đã hoạt động.

b. Background

Để push notification từ background, cần phải có service workers
Ở thư mục gốc, tạo file firebase-messaging-sw.js với nội dung sau:

//src/firebase-messaging-sw.js
import {firebaseConfig} from './src/firebase'
if ('serviceWorker' in navigator) { const firebaseConfigParams = new URLSearchParams(firebaseConfig).toString(); navigator.serviceWorker .register(`../firebase-messaging-sw.js?${firebaseConfigParams}`) .then(function (registration) { console.log('Registration successful, scope is:', registration.scope); }) .catch(function (err) { console.log('Service worker registration failed, error:', err); });
}

Ở file này mình sẽ register 1 service worker với params là firebaseConfig được import từ constants mà mình trình bày ở phần a.
Trong thư mục public, mình tạo 1 file firebase-messaging-sw.js với nội dung sau:

//public/firebase-messaging-sw.js
importScripts('https://www.gstatic.com/firebasejs/8.2.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.2.0/firebase-messaging.js'); self.addEventListener('fetch', () => { const urlParams = new URLSearchParams(location.search); self.firebaseConfig = Object.fromEntries(urlParams);
}); const defaultConfig = { apiKey: true, projectId: true, messagingSenderId: true, appId: true,
}; firebase.initializeApp(self.firebaseConfig || defaultConfig);
if (firebase.messaging.isSupported()) { const messaging = firebase.messaging(); const channel = new BroadcastChannel('notifications'); messaging.onBackgroundMessage(function (payload) { //can not console.log here channel.postMessage(payload); });
}

Đây chính là file service worker. File này sẽ initilize Firebase app và hứng message từ background.
Sau khi nhận được background message, mình sẽ muốn console.log ra để xem. Tuy nhiên do luồng service worker chạy độc lập nên sẽ không thể console.log ở trong file này.
Mình sẽ dùng BroadcastChannel để giao tiếp giữa luồng service worker và luồng web:

...
const channel = new BroadcastChannel('notifications');
...
channel.postMessage(payload);

Tiếp theo là ở luồn web, mình nhận data từ BroadcastChannel và console.log ra thôi.
Tại file App.tsx, mình thêm đoạn code vào useEffect đầu tiên, sau khi thêm thì nó sẽ như thế này:

//src/App.tsx
...
useEffect(() => { getMessagingToken(); const channel = new BroadcastChannel("notifications"); channel.addEventListener("message", (event) => { console.log("Receive background: ", event.data); }); },[])
...

Như vậy là trang web đã sẵn sàng nhận background message. Cùng thử xem nhé!
Ở trình duyệt, mình mở sang tab khác, sau đó test push message như ở phần a, và đây là kết quả khi mình quay lại tab trang Web:

Vừa rồi mình đã trình bày chức năng push notification sử dụng Firebase Cloud Messaging. Cảm ơn mọi người đã đọc bài viết!

Bình luận

Bài viết tương tự

- vừa được xem lúc

Cùng tìm hiểu về các hook trong React hooks

Đối với ai đã từng làm việc với React thì chắc hẳn đã có những lúc cảm thấy bối rối không biết nên dùng stateless (functional) component hay là stateful component. Nếu có dùng stateful component thì cũng sẽ phải loay hoay với đống LifeCycle 1 cách khổ sở Rất may là những nhà phát triển React đã kịp

0 0 81

- vừa được xem lúc

Khi nào nên (và không nên) sử dụng Redux

. Công việc quản lý state với những hệ thống lớn và phức tạp là một điều khá khó khăn cho đến khi Redux xuất hiện. Lấy cảm hứng từ design pattern Flux, Redux được thiết kế để quản lý state trong các project JavaScript.

0 0 106

- vừa được xem lúc

ReactJS: Props và State

Nếu bạn đã học ReactJS hay React Native, bạn sẽ thấy các Props và State được sử dụng rất nhiều. Vậy chính xác chúng là gì? Làm thế nào để chúng ta sử dụng chúng đúng mục đích đây.

0 0 41

- vừa được xem lúc

State và Props trong Reactjs

Hello các bạn, tiếp tục seri tìm hiểu về ReactJs hôm nay mình xin giới thiệu đến các bạn hai thứ mình cho là thú vị nhất của ReactJs là State và Props. State bạn có thể hiểu đơn giản là một nơi mà bạn lưu trữ dữ liệu của Component, từ đó bạn có thể luân chuyển dữ liệu đến các thành phần trong Compon

0 0 36

- vừa được xem lúc

Memoization trong React

. 1.Introduction. Memoization có liên quan mật thiết đến bộ nhớ đệm, và dưới đây là một ví dụ đơn giản:. const cache = {}.

0 0 38

- vừa được xem lúc

Nâng cao hiệu suất React Hooks với React.memo, Memoization và Callback Functions

1.Ngăn Re-render và React.memo. React.

0 0 67