在我的项目中,我像这样设置了 firebase:
import { initializeApp } from 'firebase/app';
import {
getMessaging,
getToken,
onMessage,
isSupported
} from 'firebase/messaging';
import store from './flag';
import { setToken } from './flag';
export const VAPID_KEY = process.env.REACT_APP_FIREBASE_VAPID_KEY
export const firebaseConfig = {
apiKey: process.env.REACT_APP_FIREBASE_apiKey,
authDomain: process.env.REACT_APP_FIREBASE_authDomain,
databaseURL: process.env.REACT_APP_FIREBASE_databaseUrl,
projectId: process.env.REACT_APP_FIREBASE_projectId,
storageBucket: process.env.REACT_APP_FIREBASE_storageBucket,
messagingSenderId: process.env.REACT_APP_FIREBASE_messagingSenderId,
appId: process.env.REACT_APP_FIREBASE_appId,
measurementId: process.env.REACT_APP_FIREBASE_measurementId
};
//Initialize Firebase Messaging
const InitializeMessaging = () => {
const app = initializeApp(firebaseConfig);
isSupported().then(is_supported => {
if (is_supported) {
requestForToken().then(fcm_token => {
store.dispatch(setToken(fcm_token));
});
}
});
};
const requestForToken = () => {
const messaging = getMessaging();
return getToken(messaging, {
vapidKey: VAPID_KEY
})
.then(currentToken => {
if (currentToken) {
return currentToken;
} else {
console.log(
'No registration token available. Request permission to generate one.'
);
}
})
.catch(err => {
console.error('An error occurred while retrieving token. ', err);
});
};
InitializeMessaging();
export const onMessageListener = () =>
new Promise(resolve => {
onMessage(getMessaging(), payload => {
resolve(payload);
});
});
我有一个商店,在收到消息后我会更改 mobx 状态(
flag.js
):
import { configureStore } from '@reduxjs/toolkit'
import { onMessageListener } from './firebase';
const initialState = { flag: true, token: "" }
function flagReducer(state = initialState, action) {
// Check to see if the reducer cares about this action
if (action.type === 'flag/change') {
// If so, make a copy of `state`
return {
...state,
// and update the copy with the new value
flag:action.payload
}
}
if (action.type === 'flag/token') {
return {
...state,
// and update the copy with the new value
token:action.payload
}
}
// otherwise return the existing state unchanged
return state
}
const store = configureStore({ reducer: flagReducer });
export const setFlag = active => ({
type: 'flag/change',
payload: active==='true'
});
export const setToken = token => ({
type: 'flag/token',
payload: token
});
onMessageListener().then(payload => {
})
.catch(err => console.log('failed: ', err));
navigator.serviceWorker.addEventListener(
'message',
function(event) {
const message = event.data.data;
if(typeof message !== 'undefined' && typeof message['flag'] !== 'undefined' ) {
store.dispatch(setFlag(message.flag));
}
}
);
export default store;
我的状态有一个从 firebase 消息切换的标志。
我还有以下工人(
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');
// Initialize the Firebase app in the service worker by passing the generated config
const firebaseConfig = {
apiKey: `REPLACE_WITH_YOUR_FIREBASE_MESSAGING_API_KEY`,
authDomain: `REPLACE_WITH_YOUR_FIREBASE_MESSAGING_AUTH_DOMAIN`,
projectId: `REPLACE_WITH_YOUR_FIREBASE_MESSAGING_PROJECT_ID`,
storageBucket: `REPLACE_WITH_YOUR_FIREBASE_MESSAGING_STORAGE_BUCKET`,
messagingSenderId: `REPLACE_WITH_YOUR_FIREBASE_MESSAGING_SENDER_ID`,
appId: `REPLACE_WITH_YOUR_FIREBASE_MESSAGING_APP_ID`,
measurementId: `REPLACE_WITH_YOUR_FIREBASE_MESSAGING_MEASUREMENT_ID`,
};
firebase.initializeApp(firebaseConfig);
// Retrieve firebase messaging
const messaging = firebase.messaging();
// Handle incoming messages while the app is not in focus (i.e in the background, hidden behind other tabs, or completely closed).
messaging.onBackgroundMessage(function(payload) {
console.log('Received background message', payload);
// How I can send the received message upon mobx
});
我想要实现的是,当我收到后台消息时,我也希望修改我所在州的标志。有办法吗?
我想要的是将消息从
firebase-messaging-sw.js
传播到 flag.js
,这样我也可以更新 redux 状态。
我的应用程序使用状态来显示基于状态标志的徽标:
import { connect } from 'react-redux';
import logo from './logo.svg';
function Logo({shown,token}){
return (
<img src={logo} className="App-logo" style={{display:!shown?"none":""}} alt="logo" />
);
}
const mapStateToProps = state => {
console.log(state);
return {
shown: state.flag,
};
};
export default connect(
mapStateToProps,
)(Logo);
这可以通过在
firebase-messaging-sw.js
放置以下内容来实现:
messaging.onBackgroundMessage(function(payload) {
console.log('Received background message', payload);
// Propagate message upon UI
if(typeof payload.data !== 'undefined' && typeof payload.data['flag'] !== 'undefined' ) {
self.clients.matchAll({includeUncontrolled: true}).then(function (clients) {
//you can see your main window client in this list.
clients.forEach(function(client) {
client.postMessage({...payload});
});
})
}
});
并在
flag.js
文件中放置:
navigator.serviceWorker.addEventListener(
'message',
function(event) {
const message = event.data.data;
if(typeof message !== 'undefined' && typeof message['flag'] !== 'undefined' ) {
store.dispatch(setFlag(message.flag));
}
}
);
上面的代码所做的是:
self.clients.matchAll({includeUncontrolled: true}).then(function (clients) {
//you can see your main window client in this list.
clients.forEach(function(client) {
client.postMessage({...payload,'type':'firebaseBG'});
});
})
我们通过一个特殊事件将消息传播回前端,该事件通过以下方式处理:
navigator.serviceWorker.addEventListener(
'message',
function(event) {
// Event handled here
}
);
消息有效负载可通过以下方式在活动中获得:
event.data.data;