When trying to send test notification from Firebase my app does not receive any event. In the notification composer I am picking specifically the fcmToken of my iOS device:
I have checked that I am using the right fcmToken and authentication keys.
Could it have something to do with the version of react-native-firebase that I am using? Or that the initialization routine is in the react-navigator?
react-native-firebase#5.5.6
react-navigation#3.11.1
Navigator.js
export default class Navigator extends Component {
constructor(props) {
super(props)
}
async componentDidMount() {
FirebaseService.checkPermission();
FirebaseService.createNotificationListeners();
}
//Remove listeners allocated in createNotificationListeners()
componentWillUnmount() {
FirebaseService.notificationListener();
FirebaseService.notificationOpenedListener();
}
render() {
return (
<View style={{ flex: 1 }}>
<Route
onNavigationStateChange={(prevState, currentState) => {
const currentScreen = getActiveRouteName(currentState);
const prevScreen = getActiveRouteName(prevState);
nav.activeRouteName = currentScreen;
if (prevScreen !== currentScreen) {
if (currentScreen == "captureView") {
this.resetSafearea("never")
} else {
this.resetSafearea("always")
}
}
}}
/>
</View>
);
}
}
FirebaseService.js
import AsyncStorage from '#react-native-community/async-storage';
import Firebase from "react-native-firebase";
export default class FirebaseService {
//1
static checkPermission = async () => {
const enabled = await Firebase.messaging().hasPermission();
if (enabled) {
FirebaseService.getToken();
} else {
FirebaseService.requestPermission();
}
}
//2
static requestPermission = async () => {
try {
await Firebase.messaging().requestPermission();
// User has authorised
FirebaseService.getToken();
} catch (error) {
// User has rejected permissions
console.log('permission rejected');
}
}
//3
static getToken = async () => {
let fcmToken = await AsyncStorage.getItem('fcmToken');
if (!fcmToken) {
fcmToken = await Firebase.messaging().getToken();
if (fcmToken) {
// user has a device token
await AsyncStorage.setItem('fcmToken', fcmToken);
}
}
return fcmToken;
}
static createNotificationListeners = async () => {
/*
* Triggered when a particular notification has been received in foreground
* */
FirebaseService.notificationListener = Firebase.notifications().onNotification((notification) => {
const { title, body } = notification;
console.log("notification", notification);
});
/*
* If your app is in background, you can listen for when a notification is clicked / tapped / opened as follows:
* */
FirebaseService.notificationOpenedListener = Firebase.notifications().onNotificationOpened((notificationOpen) => {
const { title, body } = notificationOpen.notification;
console.log("notification", notification);
});
/*
* If your app is closed, you can check if it was opened by a notification being clicked / tapped / opened as follows:
* */
const notificationOpen = await Firebase.notifications().getInitialNotification();
if (notificationOpen) {
const { title, body } = notificationOpen.notification;
console.log("notification", notification);
}
/*
* Triggered for data only payload in foreground
* */
FirebaseService.messageListener = Firebase.messaging().onMessage((message) => {
//process data message
console.log("message", JSON.stringify(message));
});
console.log("Notification listeners created.");
}
}
The reason was that the push notification certificate was not installed on my system (there was no error showing it).
You will need one for development and one for production https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/establishing_a_certificate-based_connection_to_apns
Related
So I'm basically developing a react-native Chat app using firebase as the backend and I'm stuck at this point where I am unable to send messages and not render the GiftedChat Api even. I'm pasting the Home component here can you please help me out. I'm trying to append the message to the giftedchat component and render it whenever i press the send button.
import React, { Component } from 'react' import { Text, View, Button }
from 'react-native' import { GiftedChat } from
'react-native-gifted-chat' import firebase from '../database/Firebase'
import AsyncStorage from '#react-native-community/async-storage'
class Home extends Component {
state = {
messages: [],
user: 'true',
userData: null
}
componentDidMount() {
const db = firebase.firestore()
const chatsRef = db.collection('chats')
this.readUser()
const unsubscribe = chatsRef.onSnapshot((querySnapshot) => {
const messagesFirestore = querySnapshot
.docChanges()
.filter(({ type }) => type === 'added')
.map(({ doc }) => {
const message = doc.data()
return { ...message, createdAt: message.createdAt.toDate() }
})
.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())
this.appendMessages(messagesFirestore)
})
return () => unsubscribe()
}
handleSend(messages) {
const writes = messages.map((m) => chatsRef.add(m))
Promise.all(writes)
}
appendMessages = (messages) => {
this.setState((previousMessages) => GiftedChat.append(previousMessages, messages))
}
async readUser() {
const userData = await AsyncStorage.getItem('userData')
if (userData) {
setUser(JSON.parse(userData))
}
}
async handlePress() {
const _id = Math.random().toString(36).substring(7)
const userData = { _id, name }
await AsyncStorage.setItem('userData', JSON.stringify(userData))
}
handleLogout = () => {
this.setState(() => ({
user: false
}))
}
render() {
if (this.state.user === 'true') {
return (<View>
<Button title="logout" style={{ width: 200 }} onPress={() => this.handleLogout()}></Button>
<GiftedChat messages={this.state.messages} user={this.state.userData}
onSend={() => this.handleSend()} />
</View>)
} else {
return (<View>
{this.props.navigation.navigate("Login")}
</View>)
}
} }
export default Home
We have a React-Native app on iOS and Android. We use RN 0.61.5 and react-native-firebase 5.5.6.
We use react-native-firebase/notifications to add local notifications on the device. When we test this these notifications are planned correct but we get the feedback from some of our users that they don’t receive the notifications. I have added our notifications.ts file and our NotificationListener.tsx file below.
Does someone have an idea, possible reason of tips for debug/improve/fix our notifications?
Code
notifications.ts:
// Firebase Notifications
// ---
// Custom implementation on top of the Firebase Notifications library.
// This class is responsable for creating, scheduling and re-scheduling notifications.
// ------------------------------------------------------------------------- /
import firebase from "react-native-firebase";
import { Notification } from "react-native-firebase/notifications";
import { Recycle } from "#shd-types/fp-recycle-api";
import { isEmpty } from "ramda";
import { Store } from "../../store";
import { IS_ANDROID, IS_IOS } from "../../utils/device-info";
import i18n, { manualTranslate } from "../../utils/i18n";
import { NotificationsState } from "../../features/notifications/store/notifications.types";
import { CollectionRoundsState } from "../../features/collection-rounds/store/collectionRounds.types";
import { ProfileState } from "../../features/profile/store/profile.types";
const MAX_ALLOWED_NOTIFICATIONS = 64;
class FirebaseNotifications {
private permissionsGranted: boolean = false;
private language: string;
private notificationState: NotificationsState;
private collectionRoundsState: CollectionRoundsState;
private profileState: ProfileState;
constructor() {
// Ask for permission to send notifications
this.init();
const store: any = Store.getState();
this.language = store.global.language;
this.notificationState = store.notifications;
this.collectionRoundsState = store.collectionRounds;
this.profileState = store.profile;
// Create an Android Notification Channel
// More info on this here: https://rnfirebase.io/docs/v5.x.x/notifications/android-channels
this.initChannels();
}
async init(): Promise<void> {
const store: any = Store.getState();
this.language = store.global.language;
this.notificationState = store.notifications;
this.collectionRoundsState = store.collectionRounds;
this.profileState = store.profile;
if (this.permissionsGranted) {
return Promise.resolve();
}
const enabled = await firebase.messaging().hasPermission();
if (!enabled) {
try {
await firebase.messaging().requestPermission();
this.permissionsGranted = true;
} catch (error) {
// User has rejected permissions
this.permissionsGranted = false;
return Promise.reject();
}
} else {
this.permissionsGranted = true;
}
return Promise.resolve();
}
async initChannels() {
// Create the channel groups
await firebase.notifications().android.createChannelGroups([
// Main channel group
new firebase.notifications.Android.ChannelGroup("general", "General"),
// Channel group for each address
new firebase.notifications.Android.ChannelGroup("collections-home", "Home"),
]);
// Build a channel
const channel = new firebase.notifications.Android.Channel("collection-rounds-channel", "Collection Rounds", firebase.notifications.Android.Importance.Max)
.setDescription("Notifications for Collection Rounds")
.setGroup("collections-home");
// Create the channel
firebase.notifications().android.createChannel(channel);
}
// Collection Build Methods
// ------------------------------------------------------------------------- /
setAndroidNotificationProps(notification: Notification, channelId?: string, group?: string) {
// https://rnfirebase.io/docs/v5.x.x/notifications/reference/AndroidNotification
notification
.android.setLocalOnly(true)
.android.setPriority(firebase.notifications.Android.Priority.Max)
// Notification Style
.android.setColor("green") // Sets the accent color to use
.android.setVibrate([500, 500]) // Set notification vibration pattern.
.android.setLights(0xFF97E92A, 500, 500) // Set notification light to green.
.android.setSmallIcon("ic_launcher");
if (channelId) {
notification
.android.setChannelId(channelId);
}
if (group) {
notification
.android.setGroup(group)
.android.setGroupAlertBehaviour(firebase.notifications.Android.GroupAlert.All);
}
}
setIOSNotificationProps(notification: Notification, category?: string) {
// https://rnfirebase.io/docs/v5.x.x/notifications/reference/AndroidNotification
notification
.ios.setHasAction(false); // IOS 9 only.
if (category) {
notification
.ios.setCategory(category);
}
}
buildOpenAppNotification(fireDate: number): Notification {
const notification = new firebase.notifications.Notification()
.setNotificationId(`general-open-app-reminder-${fireDate}`)
.setTitle(i18n._("notifications.appRefresh.title"))
.setBody(i18n._("notifications.appRefresh.body"))
.setSound("default")
.setData({
schedule: {
fireDate,
},
});
if (IS_ANDROID) {
this.setAndroidNotificationProps(notification, "general");
}
if (IS_IOS) {
this.setIOSNotificationProps(notification, "general");
notification
.ios.setBadge(1);
}
return notification;
}
buildCollectionNotification(collection: Recycle.Collection.CollectionRound, fireDate?: number, sameDay = false): Notification {
const collectionTypeNames = collection.types.map((collectionType: Recycle.Type.Item) => manualTranslate(collectionType.name, this.language));
const notificationTitle = sameDay
? `${i18n._("notifications.collectionSameDay.title")}: ${collectionTypeNames.join(", ")}`
: `${i18n._("notifications.collectionDayBefore.title")}: ${collectionTypeNames.join(", ")}`;
// TODO: Map this to the location, if multiple
const notificationSubtitle = i18n._(this.profileState.address[0].alias);
const notificationBody = sameDay
? i18n._("notifications.collectionSameDay.body")
: i18n._("notifications.collectionDayBefore.body");
const notificationBodyExtended = sameDay
? i18n._("notifications.collectionSameDay.bodyExtended")
: i18n._("notifications.collectionDayBefore.bodyExtended");
const notification = new firebase.notifications.Notification()
.setNotificationId(`notification-collection-${collection.id}-${fireDate}`)
.setTitle(notificationTitle)
.setSubtitle(notificationSubtitle)
.setBody(notificationBody)
.setData({
...collection,
schedule: {
fireDate,
},
})
.setSound("default");
if (IS_ANDROID) {
this.setAndroidNotificationProps(notification, "collection-rounds-channel", "collections");
notification.android
.setBigText(
notificationBodyExtended,
notificationTitle,
notificationBody
);
}
if (IS_IOS) {
this.setIOSNotificationProps(notification, "collections");
}
return notification;
}
resetNotificationBadge() {
if (IS_IOS) {
const notifications = firebase.notifications();
notifications.setBadge(0);
}
}
// Scheduling Methods
// ------------------------------------------------------------------------- /
async rescheduleNotifications(collections?: Recycle.Collection.CollectionRound[]) {
// Clear all scheduled notifications
const notifications = await firebase.notifications().getScheduledNotifications();
if (notifications) {
notifications
.forEach((notification: Notification) => {
firebase.notifications().cancelNotification(notification.notificationId);
});
}
collections = collections ? collections : this.collectionRoundsState.data;
if (!collections) {
return;
}
// Check if the user has given permission to receive notifications
try {
await this.init();
} catch (err) {
return;
}
// Fetch the notificationsSettings
const homeNotificationSettings = this.notificationState.settings.home;
// TODO
// 1. Account for the amount of notifications (e.g. the day before AND the current day)
// 2. Account for the amount of addresses to schedule for.
//
// We will simulate this for now. (simplified)
const numberOfNotificationsPerCollection = Object.values(homeNotificationSettings.time).filter((timeSetting) => timeSetting.enabled).length;
const numberOfAddresses = 1;
const numberOfCollectionsToSchedule = Math.floor(MAX_ALLOWED_NOTIFICATIONS / (numberOfAddresses * numberOfNotificationsPerCollection)) - 1;
// TODO
// 1. Account for the time when we want the notification.
let lastNotificationTime = 0;
let collectionTypesToNotNotify: string[] = [];
// Filter out the collectionTypes we don't want a notification for.
if (homeNotificationSettings) {
collectionTypesToNotNotify = Object.values(homeNotificationSettings.categories)
.filter((category) => !category.enabled )
.map((category) => category.key);
}
// Reschedule all collections
collections
.filter((collection) => {
// Filter out collections that have passed
if (new Date(collection.date).valueOf() < new Date().valueOf()) {
return false;
}
// Filter out collections that are not wanted
if (collectionTypesToNotNotify.length) {
const allow = [];
const localCollectionTypes = collection.types.map((type) => type.id);
for (const collectionType of localCollectionTypes) {
allow.push(!collectionTypesToNotNotify.includes(collectionType));
}
// The collection has at least 1 item we want notifications for.
return allow.includes(true);
}
return true;
})
.map((collection) => {
// Filter out the collections the user does not want.
if (!collectionTypesToNotNotify.length) {
return collection;
}
const localCollectionTypes = collection.types.map((type) => type.id);
return {
...collection,
types: localCollectionTypes.filter((collectionType) => {
return !collectionTypesToNotNotify.includes(collectionType);
}),
};
})
.slice(0, numberOfCollectionsToSchedule)
.forEach((collection, index, arr) => {
const collectionDay = new Date(collection.date);
let collectionNotificationTime = 0;
let collectionHour = 0;
let collectionMinutes = 0;
if (homeNotificationSettings.time.dayBefore.enabled) {
// Get the day before
const collectionNotificationDate = new Date(collectionDay).setDate(collectionDay.getDate() - 1);
// Set the notification hour
collectionHour = homeNotificationSettings.time.dayBefore.hours;
collectionMinutes = homeNotificationSettings.time.dayBefore.minutes;
collectionNotificationTime = new Date(collectionNotificationDate).setHours(collectionHour, collectionMinutes);
// Schedule the notification if it triggers in the future
this.scheduleCollectionNotification(collection, collectionNotificationTime);
}
if (homeNotificationSettings.time.dayOf.enabled) {
// Set the notification hour
collectionHour = homeNotificationSettings.time.dayOf.hours;
collectionMinutes = homeNotificationSettings.time.dayOf.minutes;
collectionNotificationTime = new Date(collectionDay).setHours(collectionHour, collectionMinutes);
// Schedule the notification if it triggers in the future
this.scheduleCollectionNotification(collection, collectionNotificationTime, true);
}
// Schedule the "open your app please" notification after 10 notifcations
// And after the last one
if ((index !== 0 && index % 10 === 0) || (index === arr.length - 1)) {
// Plan the reminder 1 day after the previous notification
const collectionDate = new Date(collectionDay).setDate(collectionDay.getDate() + 1);
lastNotificationTime = new Date(collectionDate).setHours(collectionHour, collectionMinutes);
firebase.notifications().scheduleNotification(
this.buildOpenAppNotification(lastNotificationTime),
{ fireDate: lastNotificationTime }
);
}
});
}
scheduleCollectionNotification(collection: Recycle.Collection.CollectionRound, fireDate: number, sameDay = false) {
// Schedule the notification if it triggers in the future
if (fireDate > new Date().valueOf() && !isEmpty(this.notificationState.settings.home.categories)) {
firebase.notifications().scheduleNotification(
this.buildCollectionNotification(collection, fireDate, sameDay),
{ fireDate }
);
}
}
}
export default new FirebaseNotifications();
NotificationListener.tsx:
import React from "react";
import firebase from "react-native-firebase";
import { Notification, NotificationOpen } from "react-native-firebase/notifications";
interface Props {
children: any;
}
class NotificationListener extends React.Component<Props> {
private notificationDisplayedListener: (notification?: Notification) => void;
private notificationListener: (notification?: Notification) => void;
private notificationOpenedListener: (notificationOpen?: NotificationOpen) => void;
constructor(props: Props) {
super(props);
this.notificationDisplayedListener = firebase.notifications().onNotificationDisplayed(this.onNotificationDisplayed);
this.notificationListener = firebase.notifications().onNotification(this.onNotification);
this.notificationOpenedListener = firebase.notifications().onNotificationOpened(this.onNotificationOpened);
this.onNotificationDisplayed = this.onNotificationDisplayed.bind(this);
this.onNotification = this.onNotification.bind(this);
this.onNotificationOpened = this.onNotificationOpened.bind(this);
}
// Lifecycle Methods
// ------------------------------------------------------------------------- /
// https://rnfirebase.io/docs/v5.x.x/notifications/receiving-notifications#App-Closed
async componentDidMount() {
const notificationOpen: NotificationOpen = await firebase.notifications().getInitialNotification();
if (notificationOpen) {
// App was opened by a notification
this.onNotificationOpened(notificationOpen);
}
}
componentWillUnmount() {
this.notificationDisplayedListener();
this.notificationListener();
this.notificationOpenedListener();
}
// Callback Methods
// ------------------------------------------------------------------------- /
// Triggered when a particular notification has been displayed
onNotificationDisplayed(notification: Notification) {
// ANDROID: Remote notifications do not contain the channel ID. You will have to specify this manually if you'd like to re-display the notification.
// Leave this for debugging purposes
// console.log("Notification Displayed!:", notification);
}
// Triggered when a particular notification has been received, but not displayed
onNotification(notification: Notification) {
// Leave this for debugging purposes
// console.log("Notification received, but not displayed!:", notification);
// Force the notification in the OS NotificationBar
firebase.notifications().displayNotification(notification);
}
// Triggered when a particular notification has been clicked / tapped / opened whent he app is in the foreground or background.
onNotificationOpened(notificationOpen: NotificationOpen) {
// Get the action triggered by the notification being opened
const action = notificationOpen.action;
// Get information about the notification that was opened
const notification: Notification = notificationOpen.notification;
// Leave this for debugging purposes
// console.log("Notification Opened!:", notificationOpen);
// Remove the notification once it has been openend.
firebase.notifications().removeDeliveredNotification(notificationOpen.notification.notificationId);
}
// Render Methods
// ------------------------------------------------------------------------- /
render() {
return this.props.children;
}
}
export default NotificationListener;```
I'm using firebase remote config to set the color of an Icon. The first time the app is loaded the value loaded from firebase is 0, if a reload the app i get the correct color value #ffffff.
You can see the result in Xcode console in this screenShot:
Here is my remoteConfig config file:
async getRemoteConfig(t) {
// const { t, i18n } = useTranslation();
if (__DEV__) {
firebase.config().enableDeveloperMode();
console.log('running in dev mode');
}
// Set default values
firebase.config().setDefaults({
share_button_color:'#fff'
});
firebase
.config()
.fetch(0) // call like this fetch(0) to reset cache load new params from firebase,without this it takes 12h
.then(() => {
return firebase.config().activateFetched();
})
.then(async activated => {
if (!activated) console.log('Fetched data not activated');
else console.log('Fetched data activated');
})
// .then(snapshot => {
// const hasExperimentalFeature = snapshot.val();
// if (hasExperimentalFeature) {
// enableSuperCoolFeature();
// }
// // continue booting app
// })
.catch(console.error);
},
};
Also here my component:
export default class ShareIcon extends Component {
constructor(props) {
super(props);
this.state = {
buttonColor: 'white',
};
}
async componentDidMount() {
await this.getShareButtonColor();
}
async getShareButtonColor() {
const remoteButtonColorData = await firebase
.config()
.getValue('share_button_color');
const buttonColor = remoteButtonColorData.val();
console.log('buttonColor',buttonColor) // <===this is the console.log we see
this.setState({buttonColor}); // in screenshot
}
render() {
return (
<TouchableOpacity
hitSlop={{top: 10, left: 10, bottom: 10, right: 10}}
style={styles.container}
onPress={() => shareApp()}
style={{marginLeft: 20}}>
<Icon name="share-2" type="feather" color={this.state.buttonColor} />
</TouchableOpacity>
);
}
}
I'm trying to implement Firebase Notification in my RN App. I followed this post
But when I run the code, I'm getting Hooks can only be called inside the body of a function component. There's my App.json file
export default class App extends Component {
state = {
isLoadingComplete: false,
};
render() {
return (
<SafeAreaView forceInset={{ bottom: 'never'}} style={styles.container}>
{Platform.OS === 'ios' && <StatusBar barStyle="default" />}
<Provider store={store}>
<AppNavigator/>
</Provider>
</SafeAreaView>
);
}
And functions to get the token, permissions and show alert with the remote notification. Are these functions in right place?
useEffect(() => {
this.checkPermission();
this.messageListener();
}, []);
checkPermission = async () => {
const enabled = await firebase.messaging().hasPermission();
if (enabled) {
this.getFcmToken();
} else {
this.requestPermission();
}
}
getFcmToken = async () => {
const fcmToken = await firebase.messaging().getToken();
if (fcmToken) {
console.log(fcmToken);
this.showAlert("Your Firebase Token is:", fcmToken);
} else {
this.showAlert("Failed", "No token received");
}
}
requestPermission = async () => {
try {
await firebase.messaging().requestPermission();
// User has authorised
} catch (error) {
// User has rejected permissions
}
}
messageListener = async () => {
this.notificationListener = firebase.notifications().onNotification((notification) => {
const { title, body } = notification;
this.showAlert(title, body);
});
this.notificationOpenedListener = firebase.notifications().onNotificationOpened((notificationOpen) => {
const { title, body } = notificationOpen.notification;
this.showAlert(title, body);
});
const notificationOpen = await firebase.notifications().getInitialNotification();
if (notificationOpen) {
const { title, body } = notificationOpen.notification;
this.showAlert(title, body);
}
this.messageListener = firebase.messaging().onMessage((message) => {
console.log(JSON.stringify(message));
});
}
showAlert = (title, message) => {
Alert.alert(
title,
message,
[
{text: "OK", onPress: () => console.log("OK Pressed")},
],
{cancelable: false},
);
}
}
I have no ideia what I'm missing. Maybe some function out of scope...But I can't figure out
I changed useEffect to componentDidMount() and It worked great
componentDidMount() {
this.checkPermission();
this.messageListener();
}
I have a module called Chat.js that imports Fire.js in order to send data (message comes into Chat.js, and Fire.js handles storage).
I have a recipient's user ID that is only currently available in Chat.js, but it is important to get to Fire.js in order to store appropriately.
I removed some info for brevity, this is my current Chat.js:
import Fire from './Fire';
class Chat extends React.Component<Props> {
state = {
messages: [],
};
get user() {
return {
name: this.props.navigation.state.params.name,
_id: Fire.shared.uid,
};
}
render() {
return (
<GiftedChat
messages={this.state.messages}
onSend={Fire.shared.send}
user={this.user}
/>
);
}
componentDidMount() {
Fire.shared.on(message =>
this.setState(previousState => ({
messages: GiftedChat.append(previousState.messages, message),
}))
);
}
componentWillUnmount() {
Fire.shared.off();
}
}
export default Chat;
And this is my current Fire.js:
import firebase from 'react-native-firebase';
class Fire {
constructor() {
}
get ref() {
var recipient = 'recipientId'
return firebase.database().ref('messages/' + this.uid + '/' + recipient);
}
parse = snapshot => {
const { timestamp: numberStamp, text, user } = snapshot.val();
const { key: _id } = snapshot;
const timestamp = new Date(numberStamp);
const message = {
_id,
timestamp,
text,
user,
};
return message;
};
on = callback =>
this.ref
.limitToLast(20)
.on('child_added', snapshot => callback(this.parse(snapshot)));
// send the message to the Backend
send = messages => {
for (let i = 0; i < messages.length; i++) {
const { text, user } = messages[i];
const message = {
text,
user,
timestamp: this.timestamp,
};
this.append(message);
}
};
append = message => this.ref.push(message);
// close the connection to the Backend
off() {
this.ref.off();
}
}
Fire.shared = new Fire();
export default Fire;
I currently need to get the recipient ID, which is available in chat.js under
this.props.navigation.state.params.uid
Into the Fire.js lines:
get ref()
{
var recipient = 'recipientId'
I can't seem to get this uid into get ref()
Use getter and setters in Fire.js.
In Fire.js
setRecipient (id){
this.recipientId = id;
}
get getRecipientId () {
return this.recipientId;
}
And then call Fire.setRecipient(yourId) in Chat.js.