Merge pull request #537 from invertase/docs-removal

[docs] Remove docs directory in favour of new site/docs
This commit is contained in:
Michael Diarmid 2017-10-21 12:53:12 +01:00 committed by GitHub
commit 36d974a597
56 changed files with 0 additions and 6810 deletions

View File

View File

@ -1,65 +0,0 @@
!> This is our old documentation site, please use the new and improved documentation site: https://rnfirebase.io/
<div style="text-align: center;">
[![npm version](https://img.shields.io/npm/v/react-native-firebase.svg?style=flat-square)](https://www.npmjs.com/package/react-native-firebase)
[![NPM downloads](https://img.shields.io/npm/dm/react-native-firebase.svg?style=flat-square)](https://www.npmjs.com/package/react-native-firebase)
[![Package Quality](https://npm.packagequality.com/shield/react-native-firebase.svg?style=flat-square)](http://packagequality.com/#?package=react-native-firebase)
[![License](https://img.shields.io/npm/l/react-native-firebase.svg?style=flat-square)](/LICENSE)
[![Chat](https://img.shields.io/badge/chat-on%20discord-7289da.svg?style=flat-square)](https://discord.gg/t6bdqMs)
[![Donate](https://img.shields.io/badge/Donate-Patreon-green.svg?style=flat-square)](https://www.patreon.com/invertase)
[![Twitter Follow](https://img.shields.io/twitter/follow/rnfirebase.svg?style=social&label=Follow)](https://twitter.com/rnfirebase)
</div>
---
RNFirebase is a _light-weight_ layer sitting on-top of the native Firebase libraries for both iOS and Android which mirrors the Firebase Web SDK as closely as possible.
Although the [Firebase Web SDK](https://www.npmjs.com/package/firebase) library will work with React Native, it is mainly built for the web.
RNFirebase provides a JavaScript bridge to the native Firebase SDKs for both iOS and Android therefore Firebase will run on the native thread, allowing the rest of your app to run on the [JS thread](https://facebook.github.io/react-native/docs/performance.html#javascript-frame-rate). The Firebase Web SDK also runs on the JS thread, therefore potentially affecting the frame rate causing jank with animations, touch events etc.
The native SDKs also allow us to hook into device sdk's which are not possible with the web SDK, for example crash reporting, offline realtime database support, analyics and more!
All in all, RNFirebase provides much faster performance (~2x) over the web SDK and provides device sdk's not found in the web sdk (see the feature table below).
---
## Supported Firebase Features
> The Web SDK column indicates what modules/functionality from the Web SDK are usable within React Native.
> '**?**' indicates partial support
| Firebase Features | v1.x.x | v2.x.x | v3.x.x | Web SDK |
| ---------------------- | :---: | :---: | :---: | :---: |
| **AdMob** | ❌ | ✅ | ✅ | ❌ |
| **Analytics**             | ✅ | ✅ | ✅ | ❌ |
| **App Indexing**           | ❌ | ❌ | ❌ | ❌ |
| **Authentication** | ✅ | ✅ | ✅ | ✅ |
| _-- Phone Auth_ | ❌ | ❌ | ✅ | ❌ |
| **Core** | ❌ |**?**| ✅ | ✅ |
| _-- Multiple Apps_ | ❌ | ❌ | ✅ | ✅ |
| **Cloud Messaging (FCM)** | ✅ | ✅ | ✅ |**?**|
| **Crash Reporting** | ✅ | ✅ | ✅ | ❌ |
| **Dynamic Links** | ❌ | ❌ | ✅ | ❌ |
| **Firestore** | ❌ | ❌ | ✅ | ❌ |
| **Invites** | ❌ | ❌ | ❌ | ❌ |
| **Performance Monitoring** | ✅ | ✅ | ✅ | ❌ |
| **Realtime Database** | ✅ | ✅ | ✅ | ✅ |
| _-- Offline Persistence_ | ✅ | ✅ | ✅ |**?**|
| _-- Transactions_ | ✅ | ✅ | ✅ | ✅ |
| **Remote Config** | ✅ | ✅ | ✅ | ❌ |
| **Storage** | ✅ | ✅ | ✅ |**?**|
---
### Supported versions - React Native / Firebase
> The table below shows the supported versions of React Native and the Firebase SDKs for different versions of `react-native-firebase`
| | 1.X.X | 2.0.X | 2.1.X / 2.2.X | 3.0.X |
|------------------------|-------------|-------------|-----------------|----------|
| React Native | 0.36 - 0.39 | 0.40 - 0.46 | 0.47 + | 0.48 + |
| Firebase Android SDK | 10.2.0 + | 11.0.0 + | 11.0.0 + | 11.4.2 + |
| Firebase iOS SDK | 3.15.0 + | 4.0.0 + | 4.0.0 + | 4.3.0 + |

View File

@ -1,3 +0,0 @@
- <div class="version-select"><b>Version:</b> v3.x.x</div>
- [v2.x.x](/v2/)

View File

@ -1,47 +0,0 @@
- Getting started
- [Initial setup](/initial-setup)
- [Installation - iOS](/installation-ios)
- [Installation - Android](/installation-android)
- [Usage](/usage)
- [With Expo](/faq/expo)
- [With Redux](/redux)
- [Upgrade Guide](/migration-guide)
---
- Core
- [Apps](/core/app)
- [Default App](/core/default-app)
- [Dynamically Initialize Apps](/core/initialize-apps)
- [Firebase](/core/firebase)
- [Configure RNFirebase](/core/config-rnfirebase)
---
- Modules
- [Admob (Disable Adblock)](/modules/admob)
- [Analytics](/modules/analytics)
- [Authentication](/modules/authentication)
- [Cloud Messaging](/modules/cloud-messaging)
- [Crash Reporting](/modules/crash)
- [Database](/modules/database)
- [Dynamic Links](/modules/links)
- [Firestore (Beta)](/modules/firestore)
- [Remote Config](/modules/config)
- [Storage](/modules/storage)
- [Transactions](/modules/transactions)
- [Performance Monitoring](/modules/perf)
---
- Contributing
- [Guidelines](/contributing/guidelines)
- [Testing](/contributing/testing)
---
- Other
- [Feature Requests](https://react-native-firebase.canny.io/feature-requests)
- [FAQs / Troubleshooting](/faqs)
- Chat
- [Discord](https://discord.gg/t6bdqMs)

View File

@ -1,5 +0,0 @@
# Guidelines
We welcome any contribution to the repository. Please ensure your changes to the JavaScript code follow the styling guides controlled by ESlint. Changes to native code should be kept clean and follow the standard of existing code.
Changes to existing code should ensure all relevant tests on the test app pass. Any new features should have new tests created and ensure all existing tests pass.

View File

@ -1,330 +0,0 @@
# Testing
Currently due to the blackbox Firebase enviroment, we have found the best way to test the library is to directly test against the library using a live Firebase project. As some modules also work with the offical web SDK, we can directly compare the results against our own library. This is however restrictive as it doesn't directly test the native code/modules. Plans are in place to overhaul the entire testing setup.
## Running the test app
For convenience all of the required NPM scripts are packaged with the main library to run the test app.
### Step 1 - Fork & Clone
```bash
git clone git@github.com:<username>/react-native-firebase.git
```
### Step 2 - Install dependencies
```bash
npm run tests-npm-install
```
### Step 3 - Install [WML](https://github.com/wix/wml)
WML is a library which copies files & directories to a location. This allows us to copy any changes from the library directly into the tests app, so we can quickly test changes.
```bash
npm install -g wml
```
### Step 4 - Start the watcher
```bash
npm run tests-watch-init
npm run tests-watch-start
```
### Step 5 - Start the app
```bash
npm run tests-packager
```
#### Android
Open the `tests/android` directory from Android Studio and allow Gradle to sync. Now run the app on an emulator/device.
#### iOS
First install the Pods:
```
npm run tests-pod-install
```
Open the `tests/ios/ReactNativeFirebaseDemo.xcworkspace` file in XCode and build for your preffered device or simulator.
## Tests
Tests are bootstrapped and ran when the `play` button is pressed. The status of each test suite and individual test will update as and when a test has completed or errored.
### Running tests
Tests can be run by pressing the play button in the toolbar of the app. Test can be run individually, by suite, or all at once.
![Test suite Android](https://github.com/invertase/react-native-firebase/blob/master/tests/docs/assets/test-suite-screenshot-android.png?raw=true)
### Adding test
To add tests to an existing test suite, you need to pass a function to `addTests`.
#### Synchronous tests
Synchronous tests are created by passing a function to `it`. The next test is run immediately after the last line is executed.
```javascript
testSuite.addTests(({ describe, it }) => {
describe('synchronous test', () => {
it('does something correctly', () => {
});
});
});
```
#### Asynchronous tests
Tests can be asynchronous if they return a promise. The test suite waits for the promise to resolve before executing the next test.
```javascript
testSuite.addTests(({ describe, it }) => {
describe('async successful test', () => {
it('does something correctly', () => {
return new Promise((resolve, reject) => {
// ...
resolve();
});
});
});
});
```
Asynchronous tests can also be created using the `async` function syntax:
```javascript
testSuite.addTests(({ describe, it }) => {
describe('async successful test', () => {
it('does something correctly', async () => {
// ...
await somethingAsynchronous();
});
});
});
```
> When rejecting, always ensure a valid [JavaScript Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) is provided.
### Creating a new test suite
A test suite groups together test categories under the same Firebase feature. e.g. *Realtime Database* tests.
To add a new test suite:
1. Create a new directory within `src/tests`.
2. Create an `index.js` file.
In this file, you need to create an instance of `TestSuite` - see [TestSuite constructor](#testsuite-constructor).
```javascript
import TestSuite from 'lib/TestSuite';
const MyNewSuite = new TestSuite('Realtime Database Storage', 'Upload/Download storage tests');
export default MyNewSuite;
```
3. `addTests` is then used as many times as is necessary to add tests to the test suite, accepting a function that defines one or more tests.
4. The test suite must then be imported into `src/tests/index.js` and added to `testSuiteInstances` in order for it to be included in the list of test suites available to run in the app.
## TestSuite API
### TestSuite Constructor
The TestSuite constructor accepts 3 arguments:
- **name**: String containing the name of the test suite. e.g. 'Realtime Storage'
- **description**: String containing description of the test suite
- **firebase**: This is the object exported from `src/firebase` and contains both the native and web firebase instances.
```javascript
import firebase from '../firebase';
new TestSuite('Realtime Database Storage', 'firebase.database()', firebase);
```
### Test Definition
#### describe()
The `describe()` function takes 2 - 3 arguments:
- **description**: String describing the context or target of all the tests defined in `testDefinitions`
- **options**: (Optional) object of options:
* **focus**: Boolean marking all the tests defined in `testDefinitions` (and any others marked as focused) as the only one(s) that should run
* **pending**: Boolean marking all the tests defined in `testDefinitions` as excluded from running in the test suite
- **testDefinitions**: Function that defines 1 or more tests by calling `it`, `xit` or `fit`
```javascript
function testCategory({ describe }) {
describe('a feature', () => {
it('does something synchronously', () => {
});
});
}
export default testCategory;
```
`describe()` statements can be arbitrarily nested.
#### context()
`context()` is an alias for `describe()` provided as syntactical sugar. `xcontext()` and `fcontext()` work similar to `xdescribe()` and `fdescribe()`, respectively.
#### it()
The `it()` function takes 2 - 3 arguments:
- **description**: String describing the test defined in `testDefinition`
- **options**: (Optional) object of options:
* **focus**: Boolean marking the test defined in `testDefinition` (and any others marked as focused) as the only one(s) that should run
* **pending**: Boolean marking the test defined in `testDefinition` as excluded from running in the test suite
* **timeout**: Time in milliseconds a test is allowed to execute before it's considered to have timed out. Default is 5000ms (5 seconds).
- **testDefinition**: Function that defines a test with one or more assertions. Can be a synchronous or asynchronous function. Functions that return a promise cause the test environment to wait for the promise to be resolved before proceding to the next test.
```javascript
it('does something synchronously', () => {
});
it('does something asynchronously', async () => {
});
it('does something else asynchronously', () => {
return new Promise(/* ... */);
});
```
`it()` statements can *not* be nested.
#### xdescribe() & xit()
##### Pending Tests
You can mark all tests within a `describe` statement as pending by using the `xdescribe` function instead. The test will appear greyed out and will not be run as part of the test suite.
You can mark a single test as pending by using `xit` as you would `it`.
Tests should only be marked as pending temporarily, and should not normally be committed to the test suite unless they are fully implemented.
#### fdescribe() & fit()
##### Focused Tests
You can mark all tests within a `describe` statement as focused by using the `fdescribe` function instead. Tests that are focused will be the only ones that appear and run in the test suite until all tests are removed from being focused. This is useful for running and working on a few tests at a time.
You can mark a single test as focused by using `fit` as you would `it`.
#### Test Assertions
The assertion library Should.js is used in the tests. The complete list of available assertions is available in the [Should.js documentation](https://shouldjs.github.io).
#### Lifecycle methods
Four lifecycle methods are provided for each test context:
- **before** - Run once, before the current test context executes
- **beforeEach** - Run before every test in the current test context
- **after** - Run once, after the current test context has finished executing
- **afterEach** - Run after every test in the current test context
A new test context is created when the test suite encounters any of `describe`, `xdescribe`, `fdescribe`, `context`, `xcontext` or `fcontext`, and close again when it reaches the end of the block. Test contexts can be nested and lifecycle hooks set for parent contexts apply for all descendents.
Each lifecycle hook accepts either a synchronous function, a function that returns a promise or an `async` function.
```javascript
function testCategory({ before, beforeEach, afterEach, after }) {
before(() => console.log('Before all tests start.'));
beforeEach(() => console.log('Before every test starts.'));
describe('sync successful test', function() {
// ...
});
afterEach(() => console.log('After each test starts.'));
after(() => console.log('After all tests are complete, with success or error.'));
}
```
An optional hash of options can also be passed as the first argument, defining one or more of the following values:
* **timeout**: Time in milliseconds a hook is allowed to execute before it's considered to have timed out. Default is 5000ms (5 seconds).
#### Accessing Firebase
`react-native-firebase` is available `firebase.native`:
```javascript
function testCategory({ describe, firebase }) {
describe('sync successful test', 'category', function() {
firebase.native.database();
});
}
```
If you need to access the web API for Firebase to compare with the functionality of `react-native-firebase`, you can access it on `firebase.web`.
> All tests should be written in terms of `react-native-firebase`'s behaviour and should **not** include direct comparisons with the web API. It's available for reference, only.
## Development Notes
> JavaScript changes do **not** require restarting the React Native packager to take effect
> Java changes will need to be rebuilt in Android Studio
> Objective-C changes need to be rebuilt in Xcode
### Debugging or viewing internals of the test suite
`react-native-firebase/tests` is compatible with [react-native-debugger](https://github.com/jhen0409/react-native-debugger) and is the recommended way to view the internal state of the test suite for development or troubleshooting.
It allows you to view state and prop values of the React component tree, view the actions and contents of the Redux store and view and interact with the debugging console.
Make sure **Remote JS Debugging** when running the application and close any chrome debugging windows that appear and start React Native Debugger.
### Running the internal tests
`react-native-firebase-tests` has its own tests to verify the testing framework is working as expected. These are run from the command line:
```bash
npm run internal-tests
```
## Troubleshooting
### Invalid React.podspec file: no implicit conversion of nil into String
This error occurs if you are using ruby version 2.1.2. Upgrade your version of ruby and try again.
### Unable to resolve module ../../../node_modules/react-native/packager/...
Run the packager separately, clearing the cache:
```bash
npm start -- --reset-cache
```

View File

@ -1,28 +0,0 @@
## Apps
?> For the **default** app see: [Default App](/core/default-app)
?> For initializing **additional apps** natively and also via js code over the RN bridge see: [Dynamically Initializing Apps](/core/initialize-apps)
### Reading App Options
!> `<app>.options.clientId` is not available on the **Android Firebase SDK** so will return null for Android, see the issue: [firebase/firebase-ios-sdk#140 (comment)](https://github.com/firebase/firebase-ios-sdk/issues/140#issuecomment-315953708)
Just like the Firebase web sdk you can view options used to initialize an app instance in the same way, for example:
```js
import firebase from 'react-native-firebase';
const defaultApp = firebase.app();
// get the default app name/options that the app initialized with
console.log("name", defaultApp.name);
console.log("apiKey", defaultApp.options.apiKey);
console.log("applicationId", defaultApp.options.applicationId);
console.log("databaseUrl", defaultApp.options.databaseUrl);
console.log("messagingSenderId", defaultApp.options.messagingSenderId);
console.log("projectId", defaultApp.options.projectId);
console.log("storageBucket", defaultApp.options.projectId);
```

View File

@ -1,8 +0,0 @@
<!-- TODO -->
### Log Options
TODO - PR's welcome
### Debug Options
TODO - PR's welcome

View File

@ -1,27 +0,0 @@
### Default Firebase App
After following the iOS & Android install guides and correctly setting up your google services plist/json files; the default app is automatically initialized and available for use in react-native-firebase.
There's no need to call `initializeApp(opt)` in your JS code for the default app, import RNFirebase and use the default app straight away:
```javascript
import firebase from 'react-native-firebase';
console.log(firebase.database().app.name); // '[DEFAULT]'
```
!> Calling `initializeApp()` for the default app will throw an 'app already initialized' error in a later release.
### Enable Database Persistence
Enabling database persistence (setPersistence) via JS for the default app is no longer supported. This breaking change was added in v3 to prevent several race condition issues around.
You can still however easily enable this natively for the default app instance:
#### Android
Add `FirebaseDatabase.getInstance().setPersistenceEnabled(true);` inside your `MainActivity.java` files `onCreate()` method.
#### iOS
Add `[FIRDatabase database].persistenceEnabled = YES;` after the `[FIRApp configure];` line inside your `AppDelegate.m` files `didFinishLaunchingWithOptions` method.

View File

@ -1,10 +0,0 @@
# Firebase
TODO Reference Docs:
- apps(): Array<FirebaseApp>
- app(): FirebaseApp
- initializeApp(): FirebaseApp
- setLogLevel()
- SDK_VERSION: String
- googleApiAvailability: Object

View File

@ -1,93 +0,0 @@
## Initializing Apps
!> The **default** firebase app instance can **not** be initialized via JS, please setup your google services plist/json files in your android studio / xcode projects. See [Default App](/core/default-app) for more information.
App initialization in RNFirebase is for the most part the same as the web sdk, with only a few minor differences.
### Supported Modules
Only 4 modules on the official firebase native SDK's support multiple apps, they are as follows:
- Authentication
- Database
- Firestore
- Storage
### Initialize via JavaScript
#### Cross Platform Example
```javascript
import { Platform } from 'react-native';
import firebase from 'react-native-firebase';
// pluck values from your `GoogleService-Info.plist` you created on the firebase console
const iosConfig = {
clientId: 'x',
appId: 'x',
apiKey: 'x',
databaseURL: 'x',
storageBucket: 'x',
messagingSenderId: 'x',
projectId: 'x',
// enable persistence by adding the below flag
persistence: true,
};
// pluck values from your `google-services.json` file you created on the firebase console
const androidConfig = {
clientId: 'x',
appId: 'x',
apiKey: 'x',
databaseURL: 'x',
storageBucket: 'x',
messagingSenderId: 'x',
projectId: 'x',
// enable persistence by adding the below flag
persistence: true,
};
const kittensApp = firebase.initializeApp(
// use platform specific firebase config
Platform.OS === 'ios' ? iosConfig : androidConfig,
// name of this app
'kittens',
);
// dynamically created apps aren't available immediately due to the
// asynchronous nature of react native bridging, therefore you must
// wait for an `onReady` state before calling any modules/methods
// otherwise you will most likely run into `app not initialized` exceptions
kittensApp.onReady().then((app) => {
// --- ready ---
// use `app` arg, kittensApp var or `app('kittens')` to access modules
// and their methods. e.g:
firebase.app('kittens').auth().signInAnonymously().then((user) => {
console.log('kittensApp user ->', user.toJSON());
});
});
```
### Initialize via Android/iOS native code
If you're familiar with native code you can create apps natively also (or if you are already initializing additional apps natively on app boot) - these apps automatically become available for use inside RNFirebase.
For example, if you created an app natively called `dogs` then the following would work:
```javascript
import firebase from 'react-native-firebase';
const dogsApp = firebase.app('dogs');
dogsApp.auth().signInAnonymously().then((user) => {
console.log('dogsApp user ->', user.toJSON());
});
```
### Deleting an app instance
Currently it's not possible to provide cross platform 'delete app' functionality as the Firebase Android SDK is missing the app delete method, this has been flagged with firebase ([firebase/firebase-ios-sdk#140 (comment)](https://github.com/firebase/firebase-ios-sdk/issues/140#issuecomment-315953708)).

View File

@ -1,8 +0,0 @@
### Usage With Expo
If you use Expo and would like to use this package, you'll need to eject. If you do not want to eject, but wish to make use of features
such as Realtime Database (without offline support) & Authentication, you can still use the Firebase Web SDK in your project.
For features such a Crash Reporting, Push Notifications (via Firebase not Expo), Performance Monitoring, AdMob, Analytics, Storage & Remote Config, you will have to eject your Expo project as these require the native SDKs, as the Web SDK does not support these.
You can see an indepth conversation [here](https://expo.canny.io/feature-requests/p/full-native-firebase-integration).

View File

@ -1,98 +0,0 @@
# FAQs / Troubleshooting
## Usage with Expo
See [usage with expo](/faq/expo).
## Comparison to Firestack
Firestack was a great start to integrating Firebase and React Native, however has underlying issues which needed to be fixed.
A V3 fork of Firestack was created to help address issues such as lack of standardisation with the Firebase Web SDK,
and missing core features (crash reporting, transactions etc). The volume of pull requests with fixes/features soon became
too large to manage on the existing repository, whilst trying to maintain backwards compatibility.
RNFirebase was re-written from the ground up, addressing these issues with core focus being around matching the Web SDK as
closely as possible and fixing the major bugs/issues along the way.
## [Android] Google Play Services related issues
The firebase SDK requires a certain version of Google Play Services installed on Android in order to function properly.
If the version of Google Play Services installed on your device is incorrect or non existent, React Native Firebase will throw a red box error, and your app will possibly crash as well. The red box error will have a numerical code associated with it. These codes can be found here:
https://developers.google.com/android/reference/com/google/android/gms/common/ConnectionResult#SERVICE_VERSION_UPDATE_REQUIRED
Here is a quick guide to some of the most common errors encountered:
code 2 - Google Play Services is required to run this application but no valid installation was found:
The emulator/device you're using does not have the Play Services SDK installed.
- Emulator: Open SDK manager, under 'SDK Tools' ensure "Google Play services, rev X" is installed. Once installed,
create a new emulator image. When selecting your system image, ensure the target comes "with Google APIs".
- Device: Play Services needs to be downloaded from the Google Play Store.
code 9 - The version of the Google Play services installed on this device is not authentic:
This error applies to modified or 'shimmed' versions of Google Play Services which you might be using in a third
party emulator such as GenyMotion.
Using this kind of workaround with Google Play Services can be problematic, so we
recommend using the native Android Studio emulators to reduce the chance of these complications.
## [Android] Turning off Google Play Services availability errors
G.P.S errors can be turned off using a config option like so:
```javascript
const firebase = RNFirebase.initializeApp({
errorOnMissingPlayServices: false,
});
```
This will stop your app from immediately red-boxing or crashing, but won't solve the underlying issue of G.P.S not being available or of the correct version. This will mean certain functionalities won't work properly and your app may even crash.
## [Android] Checking for Google Play Services availability with React Native Firebase
React Native Firebase actually has a useful helper object for checking G.P.S availability:
```javascript
const availability = firebase.googleApiAvailability;
```
The availability object would then have the following properties that you can run checks against:
```javascript
isAvailable: boolean
```
and if not available (isAvailable === false):
```javascript
isUserResolvableError: boolean
```
This variable indicates whether or not the end user can fix the issue, for example by downloading the required version of Google Play Services. In a case such as a GenyMotion emulator, this would return false for missing G.P.S, as the end user can't add the package directly.
```javascript
error: string
```
This error will match the messages and error codes mentioned above, and can be found here:
https://developers.google.com/android/reference/com/google/android/gms/common/ConnectionResult#SERVICE_VERSION_UPDATE_REQUIRED
## [Android] Duplicate Dex Files error (build time error)
A common build time error when using libraries that require google play services is of the form:
'Failed on android with com.android.dex.DexException: Multiple dex files... '
This error (https://github.com/invertase/react-native-firebase/issues/48) occurs because different versions of google play services or google play services modules are being required by different libraries.
The process to fix this is fairly manual and depends on your specific combination of external libraries. Essentially what's required is to check the app level build.gradle file of each external library and establish which ones have a Google Play Services dependency.
You then need to find the lowest common version of each G.P.S module dependency, require that in the app level build.gradle file of your own project, and exclude it from being required by the modules themselves. This will force the use of a consistent version of the G.P.S module.
It's not a good idea to modify the version within the library's build.gradle, as this will be overwritten when you update the library, which will lead to the build breaking again.
A good break down of this process can be found here:
https://medium.com/@suchydan/how-to-solve-google-play-services-version-collision-in-gradle-dependencies-ef086ae5c75f

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -1,401 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>React Native Firebase - A react native firebase library supporting both android and ios native firebase
SDK's</title>
<meta name="description"
content="A react native firebase library supporting both android and ios native firebase SDK's">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<link rel="shortcut icon" type="image/png"
href="./icon.png" />
</head>
<body>
<div class="rnfirebase-header">
<img src="https://static.invertase.io/assets/React-Native-Firebase.svg" alt="rnfirebase logo">
<span><a href="./">React Native Firebase</a></span>
</div>
<div id="app"></div>
</body>
<script>
window.$docsify = {
name: 'React Native Firebase - Documentation',
repo: 'https://github.com/invertase/react-native-firebase',
loadSidebar: true,
loadNavbar: true,
mergeNavbar: true,
search: 'auto',
themeColor: '#e88634',
subMaxLevel: 3,
maxLevel: 4,
ga: 'UA-98196653-1',
formatUpdated: '{DD}/{MM}/{YYYY} {HH}:{mm}',
plugins: [
function (hook, vm) {
hook.beforeEach(function (html) {
var url = 'https://github.com/invertase/react-native-firebase/blob/master/docs/' + vm.route.file;
var editHtml = '[:memo: Edit me on Github](' + url + ')\n';
return html
+ '\n----\n'
+ '<b>Last updated</b>: {docsify-updated} '
+ editHtml
})
}
],
}
</script>
<!--<script>-->
<!--if (typeof navigator.serviceWorker !== 'undefined') {-->
<!--navigator.serviceWorker.register('sw.js')-->
<!--}-->
<!--</script>-->
<link rel="stylesheet" href="//unpkg.com/docsify/themes/vue.css">
<style>
.markdown-section pre>code {
background: #383838;
}
.markdown-section pre {
background: #383838;
}
hr {
display: block;
height: 1px;
border: 0;
border-top: 1px solid #e8e8e8;
margin: 1em 0;
padding: 0;
}
code[class*="lang-"],
pre[class*="lang-"] {
color: white !important;
background: none !important;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace !important;
text-align: left !important;
text-shadow: 0 -.1em .2em black !important;
white-space: pre !important;
word-spacing: normal !important;
word-break: normal !important;
word-wrap: normal !important;
line-height: 1.5 !important;
-moz-tab-size: 4 !important;
-o-tab-size: 4 !important;
tab-size: 4 !important;
-webkit-hyphens: none !important;
-moz-hyphens: none !important;
-ms-hyphens: none !important;
hyphens: none !important;
}
pre[class*="lang-"],
:not(pre) > code[class*="lang-"] {
background: hsl(0, 0%, 8%) !important; /* #141414 */
}
/* Code blocks */
pre[class*="lang-"] {
border-radius: .5em !important;
border: .3em solid hsl(0, 0%, 33%) !important; /* #282A2B */
box-shadow: 1px 1px .5em black inset !important;
margin: .5em 0 !important;
overflow: auto !important;
padding: 1em !important;
}
pre[class*="lang-"]::-moz-selection {
/* Firefox */
background: hsl(200, 4%, 16%) !important; /* #282A2B */
}
pre[class*="lang-"]::selection {
/* Safari */
background: hsl(200, 4%, 16%) !important; /* #282A2B */
}
/* Text Selection colour */
pre[class*="lang-"]::-moz-selection, pre[class*="lang-"] ::-moz-selection,
code[class*="lang-"]::-moz-selection, code[class*="lang-"] ::-moz-selection {
text-shadow: none !important;
background: hsla(0, 0%, 93%, 0.15) !important; /* #EDEDED */
}
pre[class*="lang-"]::selection, pre[class*="lang-"] ::selection,
code[class*="lang-"]::selection, code[class*="lang-"] ::selection {
text-shadow: none !important;
background: hsla(0, 0%, 93%, 0.15) !important; /* #EDEDED */
}
/* Inline code */
:not(pre) > code[class*="lang-"] {
border-radius: .3em !important;
border: .13em solid hsl(0, 0%, 33%) !important; /* #545454 */
box-shadow: 1px 1px .3em -.1em black inset !important;
padding: .15em .2em .05em !important;
white-space: normal !important;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: hsl(0, 0%, 58%) !important; /* #777777 */
}
.token.punctuation {
opacity: .7 !important;
color: #ffffff !important;
}
.namespace {
opacity: .7 !important;
}
.token.tag,
.token.boolean,
.token.number,
.token.deleted {
color: hsl(14, 58%, 55%) !important; /* #CF6A4C */
}
.token.keyword,
.token.property,
.token.selector,
.token.constant,
.token.symbol,
.token.builtin {
color: hsl(27, 80%, 56%) !important; /* #F9EE98 */
}
.token.attr-name,
.token.attr-value,
.token.string,
.token.char,
.token.operator,
.token.entity,
.token.url,
.lang-css .token.string,
.style .token.string,
.token.variable,
.token.inserted {
color: hsl(37, 100%, 80%) !important; /* #8F9D6A */
}
.token.atrule {
color: hsl(218, 22%, 55%) !important; /* #7587A6 */
}
.token.regex,
.token.important {
color: hsl(42, 75%, 65%) !important; /* #E9C062 */
}
.token.important,
.token.bold {
font-weight: bold !important;
}
.token.italic {
font-style: italic !important;
}
.token.entity {
cursor: help !important;
}
pre[data-line] {
padding: 1em 0 1em 3em !important;
position: relative !important;
}
/* Markup */
.language-markup .token.tag,
.language-markup .token.attr-name,
.language-markup .token.punctuation {
color: hsl(33, 33%, 52%) !important; /* #AC885B */
}
/* Make the tokens sit above the line highlight so the colours don't look faded. */
.token {
position: relative !important;
z-index: 1 !important;
}
.line-highlight {
background: hsla(0, 0%, 33%, 0.25) !important; /* #545454 */
background: linear-gradient(to right, hsla(0, 0%, 33%, .1) 70%, hsla(0, 0%, 33%, 0)) !important; /* #545454 */
border-bottom: 1px dashed hsl(0, 0%, 33%) !important; /* #545454 */
border-top: 1px dashed hsl(0, 0%, 33%) !important; /* #545454 */
left: 0 !important;
line-height: inherit !important;
margin-top: 0.75em !important; /* Same as .prisms padding-top */
padding: inherit 0 !important;
pointer-events: none !important;
position: absolute !important;
right: 0 !important;
white-space: pre !important;
z-index: 0 !important;
}
.line-highlight:before,
.line-highlight[data-end]:after {
background-color: hsl(215, 15%, 59%) !important; /* #8794A6 */
border-radius: 999px !important;
box-shadow: 0 1px white !important;
color: hsl(24, 20%, 95%) !important; /* #F5F2F0 */
content: attr(data-start) !important;
font: bold 65%/1.5 sans-serif !important;
left: .6em !important;
min-width: 1em !important;
padding: 0 .5em !important;
position: absolute !important;
text-align: center !important;
text-shadow: none !important;
top: .4em !important;
vertical-align: .3em !important;
}
.line-highlight[data-end]:after {
bottom: .4em !important;
content: attr(data-end) !important;
top: auto !important;
}
body {
padding-top: 45px;
}
.section-link:hover {
text-decoration: none;
}
.app-name-link {
display: none;
}
.sidebar {
padding-top: 64px;
}
.github-corner {
height: 64px;
z-index: 9996;
}
.app-nav {
z-index: 9996;
}
.github-corner > svg {
height: 64px;
width: 64px;
}
.rnfirebase-header {
width: 100%;
height: 64px;
position: fixed;
top: 0;
left: 0;
background: #383838;
z-index: 9995;
vertical-align: middle;
box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
transition: all 0.3s cubic-bezier(.25,.8,.25,1);
}
pre {
box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23);
}
.warn {
box-shadow: 0 1px 2px rgba(0,0,0,0.16), 0 1px 2px rgba(0,0,0,0.23);
}
.tip {
box-shadow: 0 1px 2px rgba(200,0,0,0.16), 0 1px 2px rgba(0,0,0,0.23);
}
code {
box-shadow: 0 1px 2px rgba(0,0,0,0.09), 0 1px 2px rgba(0,0,0,0.13);
}
li > a > code {
box-shadow: none;
}
.rnfirebase-header > img {
float: left;
width: 45px;
height: 45px;
margin: 10px;
}
.version-select {
position: fixed;
right: 70px;
top: 13px;
background: rgb(255, 235, 213);
padding: 8px;
border: 1px solid #e88634;
width: 110px;
}
.rnfirebase-header > span {
float: left;
height: 64px;
font-size: 24px;
line-height: 64px;
color: #e88634;
text-align: center;
}
a:-webkit-any-link:hover {
text-decoration:none !important;
margin-left: 3px;
}
.rnfirebase-header > span > a {
border:none;
outline:none;
text-decoration:none;
color:inherit;
-webkit-tap-highlight-color: white;
}
.sidebar-toggle {
background-color: rgba(255, 255, 255, 0.92);
}
.app-nav li ul {
background-color: #fff;
border: 1px solid #ddd;
border-bottom-color: #ccc;
border-radius: 2px;
box-sizing: border-box;
display: none;
max-height: calc(100vh - 61px);
overflow-y: scroll;
padding: 10px 0;
position: fixed;
right: 70px;
text-align: left;
top: 50px;
white-space: nowrap;
width: 110px;
}
</style>
<script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
<script src="//unpkg.com/docsify/lib/plugins/search.js"></script>
<script src="//unpkg.com/docsify/lib/plugins/emoji.min.js"></script>
<script src="//unpkg.com/docsify/lib/plugins/ga.min.js"></script>
<script src="//unpkg.com/prismjs/components/prism-bash.min.js"></script>
<script src="//unpkg.com/prismjs/components/prism-bash.min.js"></script>
<script src="//unpkg.com/prismjs/components/prism-javascript.min.js"></script>
<script src="//unpkg.com/prismjs/components/prism-java.min.js"></script>
<script src="//unpkg.com/prismjs/components/prism-ruby.min.js"></script>
<script src="//unpkg.com/prismjs/components/prism-groovy.min.js"></script>
<script src="//unpkg.com/prismjs/components/prism-c.min.js"></script>
<script src="//unpkg.com/prismjs/components/prism-objectivec.min.js"></script>
<script src="//unpkg.com/prismjs/components/prism-swift.min.js"></script>
<script src="//unpkg.com/prismjs/components/prism-objectivec.min.js"></script>
</html>

View File

@ -1,26 +0,0 @@
# Install the library
`npm install --save react-native-firebase`
# Initial Setup
The RNFirebase library is intended on making it easy to work with [Firebase](https://firebase.google.com/) and provides a small native shim to the Firebase native code.
To add Firebase to your project, make sure to create a project in the [Firebase console](https://firebase.google.com/console)
![Create a new project](https://i.imgur.com/KbbamwD.png)
Each platform uses a different setup method after creating the project.
## Starter Project
Fresh project and want to skip most of the setup? Check out our [starter app](
http://invertase.link/starter).
## iOS
For iOS, follow the instructions [here](/installation-ios).
## Android
For Android, follow the instructions [here](/installation-android).

View File

@ -1,230 +0,0 @@
# Android Installation
## 1) Link RNFirebase
Run `react-native link react-native-firebase`
## 2) Setup google-services.json
Download the `google-services.json` file provided by Firebase in the _Add Firebase to Android_ platform menu in your Firebase configuration console. This file should be downloaded to `YOUR_PROJECT/android/app/google-services.json`.
Next you'll have to add the google-services gradle plugin in order to parse it.
Add the google-services gradle plugin as a dependency in the *project* level build.gradle
`android/build.gradle`
```groovy
buildscript {
// ...
dependencies {
// ...
classpath 'com.google.gms:google-services:3.1.1'
}
}
```
In your app build.gradle file, add the gradle plugin at the VERY BOTTOM of the file (below all dependencies)
`android/app/build.gradle`
```groovy
apply plugin: 'com.google.gms.google-services'
```
## 3) Setup Firebase
Now you need to the required Firebase dependencies in our `android/app/build.gradle` so that they are compiled as part of React Native. In the `dependencies` listing, add the appropriate `compile` lines:
```groovy
dependencies {
// This should be added already
compile(project(':react-native-firebase')) {
transitive = false
}
// RNFirebase required dependencies
compile "com.google.firebase:firebase-core:11.4.2"
compile "com.google.android.gms:play-services-base:11.4.2"
// RNFirebase optional dependencies
compile "com.google.firebase:firebase-ads:11.4.2"
compile "com.google.firebase:firebase-auth:11.4.2"
compile "com.google.firebase:firebase-config:11.4.2"
compile "com.google.firebase:firebase-crash:11.4.2"
compile "com.google.firebase:firebase-database:11.4.2"
compile "com.google.firebase:firebase-firestore:11.4.2"
compile "com.google.firebase:firebase-invites:11.4.2"
compile "com.google.firebase:firebase-messaging:11.4.2"
compile "com.google.firebase:firebase-perf:11.4.2"
compile "com.google.firebase:firebase-storage:11.4.2"
}
```
Google Play services from 11.2.0 onwards require their dependencies to be downloaded from Google's Maven respository so add the
required reference to the repositories section of the *project* level build.gradle
`android/build.gradle`
```groovy
allprojects {
repositories {
mavenLocal()
jcenter()
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url "$rootDir/../node_modules/react-native/android"
}
// -------------------------------------------------
// Add this below the existing maven property above
// -------------------------------------------------
maven {
url 'https://maven.google.com'
}
}
}
```
## 4) Install RNFirebase modules
RNFirebase is split into separate modules to allow you to only include the Firebase functionality that you need in your application.
To install `react-native-firebase` in your project, you'll need to import the packages you need from `io.invertase.firebase` in your project's `android/app/src/main/java/com/[app name]/MainApplication.java` and list them as packages for ReactNative in the `getPackages()` function:
```java
package com.youcompany.application;
// ...
// Required package
import io.invertase.firebase.RNFirebasePackage; // <-- This should be added already
// Optional packages - add as appropriate
import io.invertase.firebase.admob.RNFirebaseAdMobPackage; //Firebase AdMob
import io.invertase.firebase.analytics.RNFirebaseAnalyticsPackage; // Firebase Analytics
import io.invertase.firebase.auth.RNFirebaseAuthPackage; // Firebase Auth
import io.invertase.firebase.config.RNFirebaseRemoteConfigPackage; // Firebase Remote Config
import io.invertase.firebase.crash.RNFirebaseCrashPackage; // Firebase Crash Reporting
import io.invertase.firebase.database.RNFirebaseDatabasePackage; // Firebase Realtime Database
import io.invertase.firebase.firestore.RNFirebaseFirestorePackage; // Firebase Firestore
import io.invertase.firebase.links.RNFirebaseLinksPackage; // Firebase Links
import io.invertase.firebase.messaging.RNFirebaseMessagingPackage; // Firebase Cloud Messaging
import io.invertase.firebase.perf.RNFirebasePerformancePackage; // Firebase Performance
import io.invertase.firebase.storage.RNFirebaseStoragePackage; // Firebase Storage
// ...
public class MainApplication extends Application implements ReactApplication {
// ...
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new RNFirebasePackage(), // <-- This should be added already
// Add these packages as appropriate
new RNFirebaseAdMobPackage(),
new RNFirebaseAnalyticsPackage(),
new RNFirebaseAuthPackage(),
new RNFirebaseRemoteConfigPackage(),
new RNFirebaseCrashPackage(),
new RNFirebaseDatabasePackage(),
new RNFirebaseFirestorePackage(),
new RNFirebaseLinksPackage(),
new RNFirebaseMessagingPackage(),
new RNFirebasePerformancePackage(),
new RNFirebaseStoragePackage()
);
}
};
// ...
}
```
## 5) Cloud Messaging (optional)
If you plan on using [Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging/), add the following to `android/app/src/main/AndroidManifest.xml`.
Add permissions:
```xml
<manifest ...>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.VIBRATE" />
```
Set app [launch mode](https://inthecheesefactory.com/blog/understand-android-activity-launchmode/en) inside activity props:
```xml
<activity
...
android:launchMode="singleTop"
>
```
Add messaging service:
```xml
<application ...>
<service
android:name="io.invertase.firebase.messaging.MessagingService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service android:name="io.invertase.firebase.messaging.InstanceIdService" android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
```
If you would like to schedule local notifications then you also need to add the following:
```xml
<receiver android:name="io.invertase.firebase.messaging.RNFirebaseLocalMessagingPublisher"/>
<receiver android:enabled="true" android:exported="true" android:name="io.invertase.firebase.messaging.RNFirebaseSystemBootEventReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
```
## 6) Performance Monitoring (optional)
If you'd like to take advantage of Firebase's [Performance Monitoring](https://firebase.google.com/docs/perf-mon/), the following additions
to your project setup are required:
In your projects `android/build.gradle` file, add the plugin to your dependencies:
```groovy
dependencies {
// ...
classpath 'com.google.firebase:firebase-plugins:1.1.0'
}
```
At the top of your `android/app/build.gradle` file, below other plugins, apply the `firebase-perf` plugin:
```groovy
apply plugin: "com.android.application"
apply plugin: "com.google.firebase.firebase-perf"
```
In the same file, add the `firebase-perf` module to your dependencies:
```groovy
dependencies {
// ...
compile "com.google.firebase:firebase-perf:11.4.2"
}
```
## 7) Dynamic Links (optional)
If you plan on using [Firebase Dynamic
Links](https://firebase.google.com/docs/dynamic-links/):
Make sure to setup dynamic links for Android as described [here](https://firebase.google.com/docs/dynamic-links/android/receive#set-up-firebase-and-the-dynamic-links-sdk)
In `android/app/src/main/AndroidManifest.xml`, add a new intent filter to the activity that handles deep links for your app (for react-native this is usually MainActivity), and specify the host and the scheme:
```xml
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:host="yoursite.example.com" android:scheme="http"/>
<data android:host="yoursite.example.com" android:scheme="https"/>
</intent-filter>
```

View File

@ -1,239 +0,0 @@
# iOS Installation
Please note that there is a known issue when using Cocoapods with the `use_frameworks!` enabled. This is explained [here](https://github.com/invertase/react-native-firebase/issues/252#issuecomment-316340974). Unfortunately we don't currently have a workaround, but are engaging with Firebase directly to try and resolve the problem.
## 1) Link RNFirebase
Run `react-native link react-native-firebase`
## 2) Setup GoogleService-Info.plist
Setup the `GoogleService-Info.plist` file by following the instructions and adding it to the root of your project at `ios/[YOUR APP NAME]/GoogleService-Info.plist` [here](https://firebase.google.com/docs/ios/setup#add_firebase_to_your_app).
Adding the file into the directory doesn't automatically add the file to the iOS project. You need to then manually add it by doing the following:
- 2.1. Open `<project root>/ios/'project name'.xcworkspace` file via XCode
- 2.1.1. If you've not got a `.xcworkspace` file yet then you'll need to come back to these steps after setting up your pods + pod install (step 3 on this page)
- 2.2. Right click on your project
- 2.3. Click "Add files to 'project name'"
- 2.4. Select the .plist file you copied into your project
- 2.5. Click OK
### 2.1) Initialisation
Make sure you've added the following to the top of your `ios/[YOUR APP NAME]]/AppDelegate.m` file:
`#import <Firebase.h>`
and this to the `didFinishLaunchingWithOptions:(NSDictionary *)launchOptions` method before the `return` statement:
`[FIRApp configure];`
## 3) Setup Firebase Pods
Firebase recommends using Cocoapods to install the Firebase SDK.
### 3.0) If you don't already have Cocoapods set up
Follow the instructions to install Cocoapods and create your Podfile [here](https://firebase.google.com/docs/ios/setup#add_the_sdk).
**NOTE: The Podfile needs to be initialised in the `ios` directory of your project. Make sure to update cocoapods libs first by running `pod update`**
#### Troubleshooting
1) When running `pod install` you may encounter an error saying that a `tvOSTests` target is declared twice. This appears to be a bug with `pod init` and the way that react native is set up.
**Resolution:**
- Open your Podfile
- Remove the duplicate `tvOSTests` target nested within the main project target
- Re-run `pod install`.
2) When running `pod install` you may encounter a number of warnings relating to `target overrides 'OTHER_LDFLAGS'`.
**Resolution:**
- Open Xcode
- Select your project
- For each target:
-- Select the target
-- Click Build settings
-- Search for `other linker flags`
-- Add `$(inherited)` as the top line if it doesn't already exist
- Re-run `pod install`
3) When running `pod install` you may encounter a warning that a default iOS platform has been assigned. If you wish to specify a different minimum version:
**Resolution**
- Open your Podfile
- Uncomment the `# platform :ios, '9.0'` line by removing the `#` character
- Change the version as required
### 3.1) Check the Podfile platform version
We recommend using a minimum platform version of at least 9.0 for your application to ensure that the correct version of the Firebase libraries are used. To do this, you need to uncomment or make sure the following line is present at the top of your `Podfile`:
`platform :ios, '9.0'`
### 3.2) Add the required pods
Simply add the following to your `Podfile` either at the top level, or within the main project target:
```ruby
# Required by RNFirebase
pod 'Firebase/Core'
# [OPTIONAL PODS] - comment out pods for firebase products you won't be using.
pod 'Firebase/AdMob'
pod 'Firebase/Auth'
pod 'Firebase/Crash'
pod 'Firebase/Database'
pod 'Firebase/DynamicLinks'
pod 'Firebase/Firestore'
pod 'Firebase/Messaging'
pod 'Firebase/RemoteConfig'
pod 'Firebase/Storage'
```
Run `pod install`.
**NOTE: You need to use the `ios/[YOUR APP NAME].xcworkspace` instead of the `ios/[YOUR APP NAME].xcproj` file from now on.**
#### Troubleshooting
1) You receive an error `No podspec found for 'RNFirebase'`
**Resolution**
- Run `npm install --save react-native-firebase` from the root of your project
## 4) Cloud Messaging (optional)
If you plan on using [Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging/) then, you need to:
**NOTE: FCM does not work on the iOS simulator, you must test is using a real device. This is a restriction enforced by Apple for some unknown reason.**
### 4.1) Set up certificates
Follow the instructions at https://firebase.google.com/docs/cloud-messaging/ios/certs
### 4.2) Enable capabilities
In Xcode, enable the following capabilities:
1) Push Notifications
2) Background modes > Remote notifications
### 4.3) Update `AppDelegate.h`
Add the following import:
`@import UserNotifications;`
Change the interface descriptor to:
`@interface AppDelegate : UIResponder <UIApplicationDelegate,UNUserNotificationCenterDelegate>`
### 4.4) Update `AppDelegate.m`
Add the following import:
`#import "RNFirebaseMessaging.h"`
Add the following to the `didFinishLaunchingWithOptions:(NSDictionary *)launchOptions` method after `[FIRApp Configure]`:
`[[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];`
Add the following methods:
```objectivec
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
[RNFirebaseMessaging didReceiveLocalNotification:notification];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo {
[RNFirebaseMessaging didReceiveRemoteNotification:userInfo];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo
fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler{
[RNFirebaseMessaging didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
[RNFirebaseMessaging willPresentNotification:notification withCompletionHandler:completionHandler];
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)())completionHandler {
[RNFirebaseMessaging didReceiveNotificationResponse:response withCompletionHandler:completionHandler];
}
```
### 4.5) Debugging
If you're having problems with messages not being received, check out the following blog post for help:
https://firebase.googleblog.com/2017/01/debugging-firebase-cloud-messaging-on.html
## 5) Dynamic Links (optional)
If you plan on using [Firebase Dynamic Links](https://firebase.google.com/docs/dynamic-links/) then, you need to:
### 5.1) Setup
Make sure to setup dynamic links for iOS as described [here](https://firebase.google.com/docs/dynamic-links/ios/receive#set-up-firebase-and-the-dynamic-links-sdk)
### 5.2) create a new URL type
In the Info tab of your app's Xcode project, create a new URL type to be used for Dynamic Links. Set the Identifier field to a unique value and the URL scheme field to either your bundle identifier or a unique value.
### 5.3) Enable Associated Domains capability
In the Capabilities tab of your app's Xcode project, enable Associated Domains and
add the following to the Associated Domains list:
`applinks:app_code.app.goo.gl` where `app_code` is your dynamic links domain application code.
### 5.4) Update `AppDelegate.m`
Add the following import:
`#import "RNFirebaseLinks.h"`
Add the following to the `didFinishLaunchingWithOptions:(NSDictionary *)launchOptions` method before `[FIRApp Configure]`:
`[FIROptions defaultOptions].deepLinkURLScheme = CUSTOM_URL_SCHEME;`
where `CUSTOM_URL_SCHEME` is the custom URL scheme you defined in your Xcode project.
In the application:openURL:sourceApplication:annotation: (for iOS 8 and older) add the following:
```objectivec
- (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
options:(NSDictionary<NSString *, id> *)options {
return [RNFirebaseLinks application:application
openURL:url
options:options];
}
```
In the application:openURL:options: (for iOS 9) add the following:
```objectivec
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
return [RNFirebaseLinks application:application
openURL:url
sourceApplication:sourceApplication
annotation:annotation];
}
```
In the application:continueUserActivity:restorationHandler (Universal Links on iOS 9 and newer) add the following:
```objectivec
- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray *))restorationHandler {
return [RNFirebaseLinks application:application
continueUserActivity:userActivity
restorationHandler:restorationHandler];
}
```

View File

@ -1,100 +0,0 @@
# Migration
## From v2 to v3
The below is a quick summary of steps to take when migrating from v2 to v3 of RNFirebase. Please see the [v3 change log](https://github.com/invertase/react-native-firebase/releases/tag/v3.0.0) for detailed changes.
** Please note, we're now using `Apache License 2.0` to license this library. **
##### 1) Install the latest version of RNFirebase:
> `npm i react-native-firebase@latest --save`
##### 2) Upgrade react-native version (only if you're currently lower than v0.48):
- Follow the instructions [here](https://facebook.github.io/react-native/docs/upgrading.html)
##### 3) Update your code to reflect deprecations/breaking changes if needed:
- ![#f03c15](https://placehold.it/15/f03c15/000000?text=+) **[breaking]** [database] enabling database persistence (setPersistence) via JS is no longer supported - this is to prevent several race conditions. See sub points on how to enable these natively.
- [android] add `FirebaseDatabase.getInstance().setPersistenceEnabled(true);` to your `MainActivity` `onCreate` method.
- [ios] add `[FIRDatabase database].persistenceEnabled = YES;` after the `[FIRApp configure];` line inside your `AppDelegate` `didFinishLaunchingWithOptions` method.
- ![#f03c15](https://placehold.it/15/f03c15/000000?text=+) **[breaking]** [app] `new RNFirebase()` is no longer supported. See below for information about app initialisation.
- ![#f03c15](https://placehold.it/15/fdfd96/000000?text=+) **[deprecated]** [app] `initializeApp()` for apps that are already initialised natively (i.e. the default app initialised via google-services plist/json) will now log a deprecation warning.
- As these apps are already initialised natively there's no need to call `initializeApp` in your JS code. For now, calling it will just return the app that's already internally initialised - in a future version this will throw an `already initialized` exception.
- Accessing apps can now be done the same way as the web sdk, simply call `firebase.app()` to get the default app, or with the name of specific app as the first arg, e.g. `const meow = firebase.app('catsApp');` to get a specific app.
- ![#f03c15](https://placehold.it/15/f03c15/000000?text=+) **[breaking]** [auth] Third party providers now user `providerId` rather than `provider` as per the Web SDK. If you are manually creating your credentials, you will need to update the field name.
- ![#f03c15](https://placehold.it/15/f03c15/000000?text=+) **[breaking]** [database] Error messages and codes internally re-written to match the web sdk
- ![#f03c15](https://placehold.it/15/f03c15/000000?text=+) **[breaking]** [database] `ref.isEqual` now checks the query modifiers as well as the ref path (was just path before). With the release of multi apps/core support this check now also includes whether the refs are for the same app.
- ![#f03c15](https://placehold.it/15/f03c15/000000?text=+) **[breaking]** [database] on/off behaviour changes. Previous `off` behaviour was incorrect. A `SyncTree/Repo` implementation was added to provide the correct behaviour you'd expect in the web sdk. Whilst this is a breaking change it shouldn't be much of an issue if you've previously setup your on/off handling correctly. See #160 for specifics of this change.
- ![#f03c15](https://placehold.it/15/f03c15/000000?text=+) **[breaking]** [storage] UploadTaskSnapshot -> `downloadUrl` renamed to `downloadURL` to match web sdk
##### 4) Android - Update `android/build.gradle`:
- Check you are using google-services 3.1.0 or greater:
- You must add `maven { url 'https://maven.google.com' }` to your `android/build.gradle` as follows:
```groovy
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.3'
classpath 'com.google.gms:google-services:3.1.0' // CHECK VERSION HERE
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
mavenLocal()
jcenter()
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url "$rootDir/../node_modules/react-native/android"
}
// -------------------------------------------------
// Add this below the existing maven property above
// -------------------------------------------------
maven {
url 'https://maven.google.com'
}
}
}
```
##### 5) Android - Update `app/build.gradle`:
- You must update all your Firebase & play services dependencies to 11.4.2.
##### 6) iOS - Update podfile:
- You need to check that you're running at least version 4.3.0 of the Firebase Pods
- Run `pod outdated`
- Run `pod update`
Add the `Firebase/Firestore` if you plan on using firestore.
## From v1 to v2
See the guide on the [v2 docs](/v2/migration-guide?id=migration)

View File

@ -1,382 +0,0 @@
# AdMob
The admob module allows you to display adverts in your app, using your account from [AdMob by Google](https://www.google.co.uk/admob/). RNFirebase allows you to display Banners, Interstitials, NativeExpress Ads & Rewarded Videos.
## Initialize
Before using any AdMob feature, ensure you call the initialize method. This only needs to be done once per the apps lifecycle.
Initialize takes your AdMob App ID, where you can find on your AdMob dashboard.
> For testing purposes, you can use AdMobs test app ID "ca-app-pub-3940256099942544~3347511713".
```js
firebase.admob().initialize("ca-app-pub-3940256099942544~3347511713");
```
## Debugging
Once initialized, you can debug ((Android)[https://developers.google.com/mobile-ads-sdk/docs/dfp/android/debug]/(iOS)[https://developers.google.com/mobile-ads-sdk/docs/dfp/ios/debug])
your ads using the debug menu.
```js
firebase.admob().openDebugMenu();
```
## API
### Banner
AdMob Banners in RNFirebase are exported as a usable React component, allowing you to integrate it easily into your existing app very easily.
#### Props
| Prop | Type | Default | Description |
| ------------------- | ------------------ | --------------------------------------- | ----------------------------------------------------------------------------------- |
| size | string (See Sizes) | SMART_BANNER | Returns a sized banner (automatically sets View style) |
| unitId | string | | Your AdMob banner unit ID. |
| request | AdRequest | new AdRequest().addTestDevice().build() | An instance of AdRequest to load with the Banner |
| onAdLoaded | function | | Called when an ad is received. |
| onAdOpened | function | | Called when an ad opens an overlay that covers the screen. |
| onAdLeftApplication | function | | Called when an ad leaves the application (e.g., to go to the browser). |
| onAdClosed | function | | Called when the user is about to return to the application after clicking on an ad. |
| onAdFailedToLoad | function | | Called when an ad request failed. See Error Handling |
#### Example
```js
const Banner = firebase.admob.Banner;
const AdRequest = firebase.admob.AdRequest;
const request = new AdRequest();
request.addKeyword('foobar');
...
render() {
return (
<Banner
size={"LARGE_BANNER"}
request={request.build()}
onAdLoaded={() => {
console.log('Advert loaded and is now visible');
}}
/>
);
}
```
### Interstitial
An interstitial is a full screen advert which creates a new activity on top of React. As they need to be controlled,
allowing the developer to choose when to display them they're not available as a component. Instead they're controlled via
method calls.
A single interstitial instance can only be shown once. If you want to display another, create a new one.
To request an interstitial from AdMob, the `loadAd` method must be called with an instance of `AdRequest` (see below for full API):
#### Methods
| Method | Description |
| ------------------- | ---------------------------------------------------------------------------- |
| loadAd(AdRequest) | Loads an advert with request config |
| on(event, callback) | Listens to advert events. See Event Types for more information. |
| isLoaded() | Returns a boolean value as to whether the advert is loaded and ready to show.|
| show() | Show the advert on the device |
#### Example
```js
const advert = firebase.admob().interstitial('ca-app-pub-3940256099942544/1033173712');
const AdRequest = firebase.admob.AdRequest;
const request = new AdRequest();
request.addKeyword('foo').addKeyword('bar');
// Load the advert with our AdRequest
advert.loadAd(request.build());
advert.on('onAdLoaded', () => {
console.log('Advert ready to show.');
});
// Simulate the interstitial being shown "sometime" later during the apps lifecycle
setTimeout(() => {
if (advert.isLoaded()) {
advert.show();
} else {
// Unable to show interstitial - not loaded yet.
}
}, 1000);
```
### Native Express
An AdMob Native Express advert is much like a standard Banner, except it can be integrated seamlessly into your app using user predefined
styling (background color, positions, font size etc). Native Express adverts are exported as a usable React component.
#### Props
| Prop | Type | Default | Description |
| ------------------- | ------------------ | --------------------------------------- | ----------------------------------------------------------------------------------- |
| size | string (See Sizes) | SMART_BANNER | TODO |
| unitId | string | | Your AdMob banner unit ID. |
| request | AdRequest | new AdRequest().addTestDevice().build() | An instance of AdRequest to load with the Banner |
| video | AdRequest | new VideoOptions().build() | An instance of AdRequest to load with the Banner |
| onAdLoaded | function | | Called when an ad is received. |
| onAdOpened | function | | Called when an ad opens an overlay that covers the screen. |
| onAdLeftApplication | function | | Called when an ad leaves the application (e.g., to go to the browser). |
| onAdClosed | function | | Called when the user is about to return to the application after clicking on an ad. |
| onAdFailedToLoad | function | | Called when an ad request failed. See Event PropTypes for more information. |
| onVideoEnd | function | | Called if the advert video has ended (only called if the advert has a video). |
#### Usage
```js
const Banner = firebase.admob.Banner;
const NativeExpress = firebase.admob.NativeExpress;
const AdRequest = firebase.admob.AdRequest;
const request = new AdRequest();
request.addKeyword('foobar');
...
render() {
return (
<NativeExpress
size={"300x400"}
request={request.build()}
onAdLoaded={() => {
console.log('Advert loaded and is now visible');
}}
/>
);
}
```
### Rewarded Video
A rewarded video allows you to display a video to a user, whereby they're able to watch it to gain "rewards", or skip it
and receive nothing. For example, when a user completes a level on your gaming app, show them a video which will give them in-game
credit.
A single rewarded video instance can only be shown once. If you want to display another, create a new one.
?> It's recommended you begin loading the video as soon as possible.
To request an Rewarded Video from AdMob, the `loadAd` method must be called with an instance of `AdRequest` (see below for full API):
#### Methods
| Method | Description |
| ------------------- | ---------------------------------------------------------------------------- |
| loadAd(AdRequest) | Loads an advert with request config |
| on(event, callback) | Listens to advert events. See Event Types |
| isLoaded() | Returns a boolean value as to whether the advert is loaded and ready to show |
| show() | Show the advert on the device |
#### Example
```js
const advert = firebase.admob().rewarded('ca-app-pub-3940256099942544/1033173712');
const AdRequest = firebase.admob.AdRequest;
const request = new AdRequest();
request.addKeyword('foo').addKeyword('bar');
// Load the advert with our AdRequest
advert.loadAd(request.build());
advert.on('onAdLoaded', () => {
console.log('Advert ready to show.');
});
advert.on('onRewarded', (event) => {
console.log('The user watched the entire video and will now be rewarded!', event);
});
...
onLevelComplete()
.then(() => {
if (advert.isLoaded()) {
advert.show();
} else {
// skip...
}
});
```
### AdRequest
The AdRequest class is used to create an object to be passed to each advert request. The request is handled on AdMob,
and returns adverts tailored to the request options provided.
!> If no AdRequest is sent, the default request calls `addTestDevice`. Therefore, ensure a custom AdRequest object is passed through
in production.
##### build()
Builds the current request for AdMob to handle.
##### addTestDevice(device?: string)
Sets a device ID as a test device. If no device string is passed, a default emulator id is passed.
##### addKeyword(keyword: `string`)
Add a new keyword to relate the advert to.
##### setBirthday(date: `Date`)
Sets the user's birthday for targeting purposes.
##### setGender(gender: `male | female | unknown`)
Sets the user's gender for targeting purposes.
##### setLocation()
Sets the user's location for targeting purposes.
##### setRequestAgent(requestAgent: `string`)
Sets the request agent string to identify the ad request's origin. Third party libraries that reference the Mobile Ads SDK should call this method to denote the platform from which the ad request originated. For example, if a third party ad network called "CoolAds network" mediates requests to the Mobile Ads SDK, it should call this method with "CoolAds"
##### setContentUrl(url: `string`)
Sets the content URL for targeting purposes.
##### [android] setIsDesignedForFamilies(forFamilies: `boolean`)
If you set this value to true, you indicate that your app requires that the ad request should return a Designed for Families-compliant ad.
If you set this value to false, you indicate that your app does not require that the ad request should return a Designed for Families-compliant ad.
##### tagForChildDirectedTreatment(forChildren: `boolean`)
### VideoOptions
The VideoOptions class is used to create an object to be passed through to each advert request. If the advert returns a video,
the options are used when displaying it on the application.
?> Currently `NativeExpress` only accepts VideoOptions. If no VideoOptions are sent, the default options call `setStartMuted(true)`.
##### build()
Builds the current options for AdMob to handle.
##### setStartMuted(muted: `boolean`)
If true, any returned video will not play sound when it starts. The end user can manually enable sound on the advert interface.
## Prop Types
##### size: `String`
Sets the size of an Advert. Can be one of the following or a custom size:
| Size | Description |
| ----------------- | ------------------------------------------------------------------------------------------------------ |
| BANNER | Mobile Marketing Association (MMA) banner ad size (320x50 density-independent pixels). |
| FULL_BANNER | Interactive Advertising Bureau (IAB) full banner ad size (468x60 density-independent pixels). |
| LARGE_BANNER | Large banner ad size (320x100 density-independent pixels). |
| LEADERBOARD | Interactive Advertising Bureau (IAB) leaderboard ad size (728x90 density-independent pixels). |
| MEDIUM_RECTANGLE | Interactive Advertising Bureau (IAB) medium rectangle ad size (300x250 density-independent pixels). |
| SMART_BANNER | A dynamically sized banner that is full-width and auto-height. |
To specify a custom size, pass a string with the width and height split by an "x" (follows the Regex pattern `([0-9]+)x([0-9]+)`), e.g 320x150
?> Requesting an advert with a size which does not exist on the AdMob servers will return `admob/error-code-internal-error`.
##### unitId: `String`
The unit ID for the banner. Defaults to the testing unitId provided by Google for the advert type.
##### request: `AdRequest`
A built AdRequest object returned from `AdRequest.build()`.
##### video: `VideoOptions`
A built VideoOptions object returned from `VideoOptions.build()`.
### Events
Every advert returns common event types. On component based adverts (e.g. Banner) they're available as props and on instance based
adverts (e.g. Interstitial) they're available via the `on` method.
##### onAdLoaded(config: `Object`)
!> The config is not provided for Interstitial or Rewarded Video adverts.
On successful response from the AdMob servers. This is also called when a new banner is automatically loaded from the AdMob servers if the current one expires.
Returns an object of config data related to the loaded advert:
```js
{
hasVideoContent: boolean,
width: number,
height: number,
}
```
##### onAdOpened()
Called when the user presses the advert and it successfully opens.
##### onAdLeftApplication()
Called if the opened advert causes the user to leave the application, for example opening a URL in the browser.
##### onAdClosed()
Called when the user returns back to the application after closing an advert.
##### onAdFailedToLoad(error: `Error`)
Called when an advert fails to load. Returns a JavaScript Error with one of the following error codes.
| code | message |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| admob/error-code-internal-error | Something happened internally; for instance, an invalid response was received from the ad server. |
| admob/error-code-invalid-request | The ad request was invalid; for instance, the ad unit ID was incorrect. |
| admob/error-code-network-error | The ad request was unsuccessful due to network connectivity. |
| admob/error-code-no-fill | The ad request was successful, but no ad was returned due to lack of ad inventory. |
| admob/os-version-too-low | The current devices OS is below the minimum required version. |
##### [NativeExpress] onVideoEnd()
Called when video playback finishes playing.
##### [NativeExpress] onVideoMute(config: `Object`)
Called when the video changes mute state.
```js
{
isMuted: boolean,
}
```
##### [NativeExpress] onVideoPause()
Called when video playback is paused.
##### [NativeExpress] onVideoPlay()
Called when video playback is playing.
##### [NativeExpress] onVideoStart()
alled when video playback first begins.
##### [RewardedVideo] onRewarded(reward: `Object`)
Called when the user has been rewarded (usually for watching an entire video). Returns a reward object:
```js
{
type: string,
amount: number,
}
```
##### [RewardedVideo] onRewardedVideoStarted()
Called when a rewarded video has started to play.
## Statics
The following statics are available on the `firebase.admob` instance.
### Banner
Exports a React component to display an AdMob Banner.
### NativeExpress
Exports a React component to display an AdMob Native Express advert.
### AdRequest
Used to build a request object to pass into AdMob requests.
### VideoOptions
Used to build an options object for how videos should be handled with adverts containing a video.
### EventTypes
Returns all of the available advert event types.
### RewardedVideoEventTypes
Returns the extra event types for Rewarded Videos.
### NativeExpressEventTypes
Returns the extra event types for Native Express adverts.

View File

@ -1,90 +0,0 @@
# Analytics
Integrating Firebase analytics is simple. A number of methods are provided to help tailor analytics specifically for your
own app. The Firebase SDK includes a number of pre-set events which are automatically handled, and cannot be used with custom `logEvent` events:
```
'app_clear_data',
'app_uninstall',
'app_update',
'error',
'first_open',
'first_visit',
'first_open_time',
'first_visit_time',
'in_app_purchase',
'notification_dismiss',
'notification_foreground',
'notification_open',
'notification_receive',
'os_update',
'session_start',
'screen_view',
'user_engagement',
'ad_impression',
'ad_click',
'ad_query',
'ad_exposure',
'adunit_exposure',
'ad_activeiew',
```
#### `logEvent(event: string, params?: Object): void`
Log a custom event with optional params.
```javascript
firebase.analytics().logEvent('clicked_advert', { id: 1337 });
```
#### `setAnalyticsCollectionEnabled(enabled: boolean): void`
Sets whether analytics collection is enabled for this app on this device.
```javascript
firebase.analytics().setAnalyticsCollectionEnabled(false);
```
#### `setCurrentScreen(screenName: string, screenClassOverride?: string): void`
Sets the current screen name, which specifies the current visual context in your app.
> Whilst `screenClassOverride` is optional, it is recommended it is always sent as your current class name, for example on Android it will always show as 'MainActivity' if not specified.
```javascript
firebase.analytics().setCurrentScreen('user_profile');
```
#### `setMinimumSessionDuration(miliseconds: number): void`
Sets the minimum engagement time required before starting a session. The default value is 10000 (10 seconds).
```javascript
firebase.analytics().setMinimumSessionDuration(15000);
```
#### `setSessionTimeoutDuration(miliseconds: number): void`
Sets the duration of inactivity that terminates the current session. The default value is 1800000 (30 minutes).
```javascript
firebase.analytics().setSessionTimeoutDuration(900000);
```
#### `setUserId(id: string): void`
Gives a user a unique identification.
```javascript
const id = firebase.auth().currentUser.uid;
firebase.analytics().setUserId(id);
```
#### `setUserProperty(name: string, value: string): void`
Sets a key/value pair of data on the current user.
```javascript
firebase.analytics().setUserProperty('nickname', 'foobar');
```

View File

@ -1,324 +0,0 @@
# Authentication
RNFirebase handles authentication for us out of the box, both with email/password-based authentication and through oauth providers (with a separate library to handle oauth providers, see [examples](#examples)).
> Authentication requires Google Play services to be installed on Android.
## Auth
### Properties
##### `authenticated: boolean` - Returns the current Firebase authentication state.
##### `currentUser: User | null` - Returns the currently signed-in user (or null). See the [User](/modules/authentication.md#user) class documentation for further usage.
### Methods
#### [`onAuthStateChanged(event: Function): Function`](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#onAuthStateChanged)
Listen for changes in the users auth state (logging in and out). This method returns a unsubscribe function to stop listening to events. Always ensure you unsubscribe from the listener when no longer needed to prevent updates to components no longer in use.
```javascript
class Example extends React.Component {
constructor() {
super();
this.unsubscribe = null;
}
componentDidMount() {
this.unsubscribe = firebase.auth().onAuthStateChanged((user) => {
if (user) {
// User is signed in.
}
});
}
componentWillUnmount() {
if (this.unsubscribe) {
this.unsubscribe();
}
}
}
```
#### [`createUserWithEmailAndPassword(email: string, password: string): Promise`](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#createUserWithEmailAndPassword)
We can create a user by calling the `createUserWithEmailAndPassword()` function.
The method accepts two parameters, an email and a password.
```javascript
firebase.auth().createUserWithEmailAndPassword('foo@bar.com', '123456')
.then((user) => {
console.log('user created', user)
})
.catch((err) => {
console.error('An error occurred', err);
});
```
#### [`signInWithEmailAndPassword(email: string, password: string): Promise`](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#signInWithEmailAndPassword)
To sign a user in with their email and password, use the `signInWithEmailAndPassword()` function.
It accepts two parameters, the user's email and password:
```javascript
firebase.auth().signInWithEmailAndPassword('foo@bar.com', '123456')
.then((user) => {
console.log('User successfully logged in', user)
})
.catch((err) => {
console.error('User signin error', err);
});
```
#### [`signInAnonymously(): Promise`](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#signInAnonymously)
Sign an anonymous user. If the user has already signed in, that user will be returned.
```javascript
firebase.auth().signInAnonymously()
.then((user) => {
console.log('Anonymous user successfully logged in', user)
})
.catch((err) => {
console.error('Anonymous user signin error', err);
});
```
#### [`signInWithCredential(credential: Object): Promise`](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#signInWithCredential)
Sign in the user with a 3rd party credential provider. `credential` requires the following properties:
```javascript
{
provider: string,
token: string,
secret: string
}
```
```javascript
const credential = {
provider: 'facebook',
token: '12345',
secret: '6789',
};
firebase.auth().signInWithCredential(credential)
.then((user) => {
console.log('User successfully signed in', user)
})
.catch((err) => {
console.error('User signin error', err);
});
```
#### [`signInWithCustomToken(token: string): Promise`](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#signInWithCustomToken)
Sign a user in with a self-signed [JWT](https://jwt.io) token.
To sign a user using a self-signed custom token, use the `signInWithCustomToken()` function. It accepts one parameter, the custom token:
```javascript
firebase.auth().signInWithCustomToken('12345')
.then((user) => {
console.log('User successfully logged in', user)
})
.catch((err) => {
console.error('User signin error', err);
});
```
#### [`sendPasswordResetEmail(email: string): Promise`](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#sendPasswordResetEmail)
Sends a password reset email to the given email address. Unlike the web SDK, the email will contain a password reset link rather than a code.
```javascript
firebase.auth().sendPasswordResetEmail('foo@bar.com')
.then(() => {
console.log('Password reset email sent');
})
.catch((error) => {
console.error('Unable send password reset email', error);
});
```
#### [`signOut(): Promise`](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#confirmPasswordReset)
Completes the password reset process, given a confirmation code and new password.
```javascript
firebase.auth().signOut()
.then(() => {
console.log('User signed out successfully');
})
.catch();
```
## User
User class returned from `firebase.auth().currentUser`.
### Properties
##### `displayName: string | null` - The user's display name (if available).
##### `email: string | null` - The user's email address (if available).
##### `emailVerified: boolean` - True if the user's email address has been verified.
##### `isAnonymous: boolean`
##### `photoURL: string | null` - The URL of the user's profile picture (if available).
##### `providerData: Object | null` - Additional provider-specific information about the user.
##### `providerId: string | null` - The authentication provider ID for the current user. For example, 'facebook.com', or 'google.com'.
##### `uid: string` - The user's unique ID.
### Methods
#### [`delete(): Promise`](https://firebase.google.com/docs/reference/js/firebase.User#delete)
Delete the current user.
```javascript
firebase.auth().currentUser
.delete()
.then()
.catch();
```
#### [`getToken(): Promise`](https://firebase.google.com/docs/reference/js/firebase.User#getToken)
Returns the users authentication token.
```javascript
firebase.auth().currentUser
.getToken()
.then((token) => {})
.catch();
```
#### [`reauthenticate(credential: Object): Promise`](https://firebase.google.com/docs/reference/js/firebase.User#reauthenticate)
Reauthenticate the current user with credentials:
```javascript
{
provider: string,
token: string,
secret: string
}
```
```javascript
const credentials = {
provider: 'facebook',
token: '12345',
secret: '6789',
};
firebase.auth().currentUser
.reauthenticate(credentials)
.then()
.catch();
```
#### [`reload(): Promise`](https://firebase.google.com/docs/reference/js/firebase.User#reload)
Refreshes the current user.
```javascript
firebase.auth().currentUser
.reload()
.then((user) => {})
.catch();
```
#### [`sendEmailVerification(): Promise`](https://firebase.google.com/docs/reference/js/firebase.User#sendEmailVerification)
Sends a verification email to a user. This will Promise reject is the user is anonymous.
```javascript
firebase.auth().currentUser
.sendEmailVerification()
.then()
.catch();
```
#### [updateEmail(email: string)](https://firebase.google.com/docs/reference/js/firebase.User#updateEmail)
Updates the user's email address. See Firebase docs for more information on security & email validation. This will Promise reject is the user is anonymous.
```javascript
firebase.auth().currentUser
.updateEmail('foo@bar.com')
.then()
.catch();
```
#### [updatePassword(password: string)](https://firebase.google.com/docs/reference/js/firebase.User#updatePassword)
Important: this is a security sensitive operation that requires the user to have recently signed in. If this requirement isn't met, ask the user to authenticate again and then call firebase.User#reauthenticate. This will Promise reject is the user is anonymous.
```javascript
firebase.auth().currentUser
.updatePassword('foobar1234')
.then()
.catch();
```
#### [updateProfile(profile: Object)](https://firebase.google.com/docs/reference/js/firebase.User#updateProfile)
Updates a user's profile data. Profile data should be an object of fields to update:
```javascript
{
displayName: string,
photoURL: string,
}
```
```javascript
firebase.auth().currentUser
.updateProfile({
displayName: 'Display Name'
})
.then()
.catch();
```
## Examples
### Facebook authentication with react-native-fbsdk and signInWithCredential
```javascript
import { AccessToken, LoginManager } from 'react-native-fbsdk';
// ... somewhere in your login screen component
LoginManager
.logInWithReadPermissions(['public_profile', 'email'])
.then((result) => {
if (result.isCancelled) {
return Promise.resolve('cancelled');
}
console.log(`Login success with permissions: ${result.grantedPermissions.toString()}`);
// get the access token
return AccessToken.getCurrentAccessToken();
})
.then(data => {
// create a new firebase credential with the token
const credential = firebase.auth.FacebookAuthProvider.credential(data.accessToken);
// login with credential
return firebase.auth().signInWithCredential(credential);
})
.then((currentUser) => {
if (currentUser === 'cancelled') {
console.log('Login cancelled');
} else {
// now signed in
console.warn(JSON.stringify(currentUser.toJSON()));
}
})
.catch((error) => {
console.log(`Login fail with error: ${error}`);
});
```

View File

@ -1,159 +0,0 @@
# Cloud Messaging
Firebase Cloud Messaging ([FCM](https://firebase.google.com/docs/cloud-messaging/)) allows you to send push messages at no
cost to both Android & iOS platforms. Assuming the installation instructions have been followed, FCM is ready to go.
As the Firebase Web SDK has limited messaging functionality, the following methods within `react-native-firebase` have been
created to handle FCM in the React Native environment.
Badge notification is well known on the iOS platform, but also supported by different Android devices / launchers.
This library uses the [ShortcutBadger](https://github.com/leolin310148/ShortcutBadger) library to set the badge number
also on Android. A list of supported launcher can be found there.
!> [iOS] Please note: In order for iOS devices to receive Cloud Messages, ensure you [request permissions](http://invertase.io/react-native-firebase/#/modules/cloud-messaging?id=ios-requestpermissions).
## API
### subscribeToTopic(topic: string)
Subscribes the device to a topic.
```javascript
firebase.messaging().subscribeToTopic('foobar');
```
### unsubscribeFromTopic(topic: string)
Unsubscribes the device from a topic.
```javascript
firebase.messaging().unsubscribeFromTopic('foobar');
```
### getInitialNotification(): `Promise<Object>`
When the application has been opened from a notification `getInitialNotification` is called and the notification payload
is returned. Use `onMessage` for notifications when the app is running.
```javascript
firebase.messaging().getInitialNotification()
.then((notification) => {
console.log('Notification which opened the app: ', notification);
});
```
### getToken(): `Promise<string>`
Returns the devices FCM token. This token can be used in the Firebase console to send messages to directly.
```javascript
firebase.messaging().getToken()
.then((token) => {
console.log('Device FCM Token: ', token);
});
```
### deleteInstanceId(): `Promise<any>`
Reset Instance ID and revokes all tokens.
```javascript
firebase.messaging().deleteInstanceId()
.then(() => {
console.log('Deleted instance id successfully');
})
.catch((error: any) => {
console.log(`Cannot delete instance id: ${error.message}`);
});
```
### onTokenRefresh(listener: `Function<string>`)
On the event a devices FCM token is refreshed by Google, the new token is returned in a callback listener.
```javascript
firebase.messaging().onTokenRefresh((token) => {
console.log('Refreshed FCM token: ', token);
});
```
### onMessage(listener: `Function<Object>`)
On a new message, the payload object is passed to the listener callback. This method is only triggered when the app is
running. Use `getInitialNotification` for notifications which cause the app to open.
```javascript
firebase.messaging().onMessage((message) => {
// TODO
});
```
### createLocalNotification(notification: Object)
Create a local notification from the device itself.
// TODO
### scheduleLocalNotification(notification: Object)
Schedule a local notification to be shown on the device.
### getScheduledLocalNotifications(): `Promise<Array>`
Returns an array of all currently scheduled notifications.
```javascript
firebase.messaging().getScheduledLocalNotifications()
.then((notifications) => {
console.log('Current scheduled notifications: ', notifications);
});
```
### cancelLocalNotification(id: string)
Cancels a location notification by ID, or all notifications by `*`.
```javascript
// Cancel all local notifications
firebase.messaging().cancelLocalNotification('*');
// Cancel a single local notification
firebase.messaging().cancelLocalNotification('123');
```
### removeDeliveredNotification(id: string)
Removes all delivered notifications from device by ID, or all notifications by `*`.
```javascript
// Remove all notifications
firebase.messaging().removeDeliveredNotification('*');
// Removes a single local notification
firebase.messaging().removeDeliveredNotification('123');
```
### [iOS] requestPermissions()
Requests app notification permissions in an Alert dialog.
```javascript
firebase.messaging().requestPermissions();
```
### setBadgeNumber(value: number)
Sets the badge number on the iOS app icon.
```javascript
firebase.messaging().setBadgeNumber(2);
```
### getBadgeNumber(): `Promise<number>`
Returns the current badge number on the app icon.
```javascript
firebase.messaging().getBadgeNumber()
.then((badgeNumber) => {
console.log('Current badge number: ', badgeNumber);
});
```

View File

@ -1,149 +0,0 @@
# Remote Config
?> Remote Config is not available on the web SDK. Please read the [documentation](https://firebase.google.com/docs/remote-config) on when & why Remote Config benefits your app.
## API
### enableDeveloperMode()
Enable Remote Config developer mode to allow for frequent refreshes of the cache.
```js
firebase.config().enableDeveloperMode();
```
### setDefaults(defaults: `Object`)
Sets default values for the app to use when accessing values. Any data fetched and activated will override any default values.
Any values in the defaults but not on Firebase will be untouched.
```js
firebase.config().setDefaults({
hasExperimentalFeature: false,
});
```
### fetch(duration?: `number`): `Promise<String>`
Fetches the remote config data from Firebase, defined in the dashboard.
If duration is defined (seconds), data will be locally cached for this duration.
The default duration is 43200 seconds (12 hours). To force a cache refresh call the method with a duration of 0.
Thrown errors can be one of the following:
* config/failure - Config fetch failed.
* config/no_fetch_yet - Config has never been fetched.
* config/throttled - Config fetch was throttled.
```js
firebase.config()
.fetch()
.then(() => {
console.log('Successfully fetched data');
})
.catch((error) => {
console.error('Unable to fetch remote config data: ', error);
});
```
### activateFetched(): `Promise<Boolean>`
Moves fetched data in the apps active config. Always successfully resolves with a boolean value.
```js
firebase.config()
.activateFetched()
.then((success) => {
if (success) {
console.log('Successfully activated fetched config into active config');
} else {
console.log('No fetched config was found or fetched config is already active');
}
});
```
### getValue(key: `String`): `Promise<Object>`
Gets a config item by key. Returns an object containing source (default, remote or static) and val function.
```js
firebase.config()
.getValue('foobar')
.then((snapshot) => {
console.log('Got value from source: ', snapshot.source);
console.log('Value of foobar: ', snapshot.val());
})
.catch(console.error);
```
### getValues(keys: `Array<String>`): `Promise<Object>`
Gets multiple values by key. Returns an object of keys with the same object returned from `getValue`.
```js
firebase.config()
.getValues(['foobar', 'barbaz'])
.then((snapshot) => {
console.log('Value of foobar: ', snapshot.foobar.val());
console.log('Value of barbaz: ', snapshot.barbaz.val());
})
.catch(console.error);
```
### getKeysByPrefix(prefix?: `String`): `Promise <Array<String>>`
Returns all keys as an array by a prefix. If no prefix is defined all keys are returned.
```js
firebase.config()
.getKeysByPrefix()
.then((keys) => {
console.log('Current keys: ', keys);
});
```
### setDefaultsFromResource(filename: `String`)
Sets the default values from a resource:
* Android: Id for the XML resource, which should be in your application's res/xml folder.
* iOS: The plist file name, with no file name extension
```js
// Anrdoid
firebase.config().setDefaultsFromResource(1337);
// iOS
firebase.config().setDefaultsFromResource('configDefaults');
```
## Usage
```js
if (__DEV__) {
firebase.config().enableDeveloperMode();
}
// Set default values
firebase.config().setDefaults({
hasExperimentalFeature: false,
});
firebase.config().fetch()
.then(() => {
return firebase.config().activateFetched();
})
.then((activated) => {
if (!activated) console.log('Fetched data not activated');
return firebase.config().getValue('hasExperimentalFeature');
})
.then((snapshot) => {
const hasExperimentalFeature = snapshot.val();
if(hasExperimentalFeature) {
// enableSuperCoolFeature();
}
// continue booting app
})
.catch(console.error);
```

View File

@ -1,54 +0,0 @@
# Crash Reporting
RNFirebase provides crash reporting for your app out of the box. Please note crashes do not appear in real-time on the console, they tend to take a number of hours to appear.
## Enabling/Disabling Crash Reporting
By default crash reporting is enabled. If you want to disable reporting, call `setCrashCollectionEnabled(enabled: Boolean)`:
```js
firebase.crash().setCrashCollectionEnabled(false);
```
To check if crash reporting is currently enabled, call `isCrashCollectionEnabled(): Promise<boolean>`:
```js
firebase.crash().isCrashCollectionEnabled()
.then((enabled) => {
if (enabled) {
console.log('Crash Reporting is currently enabled');
}
});
```
## Manual Crash Reporting
If you want to manually report a crash, such as a pre-caught exception this is possible by using the `report` method.
```javascript
try {
initSomeSDK();
} catch (e) {
firebase.crash().log('Some SDK failed to boot!');
firebase.crash().report(e);
}
```
### log
Logs a message that will appear in a subsequent crash report.
`firebase.crash().log(String message);`
### logcat
- **Android**: Logs a message that will appear in a subsequent crash report as well as in [logcat](https://developer.android.com/studio/command-line/logcat.html).
- **iOS**: Logs the message in the subsequest crash report only (same as `log`).
`firebase.crash().logcat(int level, String tag, String message);`
### report
Files a crash report, along with any previous logs to Firebase. An [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) object must be passed into the report method.
`firebase.crash().report(Error, int maxStackSize)`.

View File

@ -1,204 +0,0 @@
# Realtime Database
RNFirebase mimics the [Web Firebase SDK Realtime Database](https://firebase.google.com/docs/database/web/read-and-write), whilst
providing support for devices in low/no data connection state.
All real time Database operations are accessed via `database()`.
Basic read example:
```javascript
firebase.database()
.ref('posts')
.on('value', (snapshot) => {
const value = snapshot.val();
});
```
Basic write example:
```javascript
firebase.database()
.ref('posts/1234')
.set({
title: 'My awesome post',
content: 'Some awesome content',
});
```
## Unmounted components
Listening to database updates on unmounted components will trigger a warning:
> Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the undefined component.
It is important to always unsubscribe the reference from receiving new updates once the component is no longer in use.
This can be achived easily using [Reacts Component Lifecycle](https://facebook.github.io/react/docs/react-component.html#the-component-lifecycle) events:
Always ensure the handler function provided is of the same reference so RNFirebase can unsubscribe the ref listener.
```javascript
class MyComponent extends Component {
constructor() {
super();
this.ref = null;
}
// On mount, subscribe to ref updates
componentDidMount() {
this.ref = firebase.database().ref('posts/1234');
this.ref.on('value', this.handlePostUpdate);
}
// On unmount, ensure we no longer listen for updates
componentWillUnmount() {
if (this.ref) {
this.ref.off('value', this.handlePostUpdate);
}
}
// Bind the method only once to keep the same reference
handlePostUpdate = (snapshot) => {
console.log('Post Content', snapshot.val());
}
render() {
return null;
}
}
```
## Usage in offline environments
### Reading data
Firebase allows the database instance to [persist on disk](https://firebase.google.com/docs/database/android/offline-capabilities) if enabled.
To enable database persistence, pass the configuration option `persistence` before calls are made:
```javascript
const configurationOptions = {
persistence: true
};
const firebase = new RNFirebase(configurationOptions);
```
Any subsequent calls to Firebase stores the data for the ref on disk.
### Writing data
Out of the box, Firebase has great support for writing operations in offline environments. Calling a write command whilst offline
will always trigger any subscribed refs with new data. Once the device reconnects to Firebase, it will be synced with the server.
The following todo code snippet will work in both online and offline environments:
```javascript
// Assume the todos are stored as an object value on Firebase as:
// { name: string, complete: boolean }
class ToDos extends Component {
constructor() {
super();
this.ref = null;
this.listView = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2,
});
this.state = {
todos: this.listView.cloneWithRows({}),
};
// Keep a local reference of the TODO items
this.todos = {};
}
// Load the Todos on mount
componentDidMount() {
this.ref = firebase.database().ref('users/1234/todos');
this.ref.on('value', this.handleToDoUpdate);
}
// Unsubscribe from the todos on unmount
componentWillUnmount() {
if (this.ref) {
this.ref.off('value', this.handleToDoUpdate);
}
}
// Handle ToDo updates
handleToDoUpdate = (snapshot) => {
this.todos = snapshot.val() || {};
this.setState({
todos: this.listView.cloneWithRows(this.todos),
});
}
// Add a new ToDo onto Firebase
// If offline, this will still trigger an update to handleToDoUpdate
addToDo() {
firebase.database()
.ref('users/1234/todos')
.set({
...this.todos, {
name: 'Yet another todo...',
complete: false,
},
});
}
// Render a ToDo row
renderToDo(todo) {
// Dont render the todo if its complete
if (todo.complete) {
return null;
}
return (
<View>
<Text>{todo.name}</Text>
</View>
);
}
// Render the list of ToDos with a Button
render() {
return (
<View>
<ListView
dataSource={this.state.todos}
renderRow={(...args) => this.renderToDo(...args)}
/>
<Button
title={'Add ToDo'}
onPress={() => this.addToDo}
/>
<View>
);
}
```
#### Differences between `.on` & `.once`
With persistence enabled, any calls to a ref with `.once` will always read the data from disk and not contact the server.
On behaves differently, by first checking for a connection and if none exists returns the persisted data. If it successfully connects
to the server, the new data will be returned and the disk data will be updated.
The database refs has a `keepSynced()` function to tell the RNFirebase library to keep the data at the `ref` in sync.
```javascript
const ref = firebase.database
.ref('chat-messages')
.child('roomId');
ref.keepSynced(true);
```
#### Security rules and offline persistence
Bear in mind that security rules live on the firebase server and **not in the client**. In other words, when offline, your app knows nothing about your database's security rules. This can lead to unexpected behaviour, which is explained in detail in the following blog post: https://firebase.googleblog.com/2016/11/what-happens-to-database-listeners-when-security-rules-reject-an-update.html
Some examples of behaviour you may not expect but may encounter are:
- Values that should not be readable, according to your security rules, are readable if they were created on the same device.
- Values are readable even when not authenticated, if they were created on the same device.
- Locations are writable even when they should not be, according to your security rules. This is more likely to cause unwanted behaviour when your app is offline, because when it is *online* the SDK will very quickly roll back the write once the server returns a permission error.

View File

@ -1,192 +0,0 @@
# Firestore (Beta)
RNFirebase mimics the [Firestore Web SDK](https://firebase.google.com/docs/reference/js/firebase.firestore) by providing a bridge to the native Android and iOS Firestore SDK's.
All Firestore operations are accessed via `firebase.firestore()`. For detailed documentation of the supported methods demonstrated below please use the official firestore web sdk guides.
?> Please note that Persistence (offline support) is enabled by default with Firestore on iOS and Android.
## Add and Manage Data
### Collections
Read information about a collection example:
```javascript
import firebase from 'react-native-firebase';
firebase.firestore()
.collection('posts')
.get()
.then(querySnapshot => {
// Access all the documents in the collection
const docs = querySnapshot.docs;
// Access the list of document changes for the collection
const changes = querySnapshot.docChanges;
// Loop through the documents
querySnapshot.forEach((doc) => {
const value = doc.data();
})
})
```
Add to a collection example (generated ID):
```javascript
import firebase from 'react-native-firebase';
firebase.firestore()
.collection('posts')
.add({
title: 'Amazing post',
})
.then(() => {
// Document added to collection and ID generated
// Will have path: `posts/{generatedId}`
})
```
Add to a collection example (manual ID):
```javascript
import firebase from 'react-native-firebase';
firebase.firestore()
.collection('posts')
.doc('post1')
.set({
title: 'My awesome post',
content: 'Some awesome content',
})
.then(() => {
// Document added to collection with path: `posts/post1`
})
```
### Documents
There are multiple ways to read a document. The following are equivalent examples:
```javascript
import firebase from 'react-native-firebase';
firebase.firestore()
.doc('posts/posts1')
 .get()
 .then((documentSnapshot) => {
const value = documentSnapshot.data();
});
firebase.firestore()
.collection('posts')
.doc('posts1')
 .get()
 .then((documentSnapshot) => {
const value = documentSnapshot.data();
});
```
Create a document example:
```javascript
import firebase from 'react-native-firebase';
firebase.firestore()
.doc('posts/posts1')
.set({
title: 'My awesome post',
content: 'Some awesome content',
})
.then(() => {
// Document created
});
```
Updating a document example:
```javascript
import firebase from 'react-native-firebase';
firebase.firestore()
.doc('posts/posts1')
.update({
title: 'My awesome post',
})
.then(() => {
// Document created
});
```
Deleting a document example:
```javascript
import firebase from 'react-native-firebase';
firebase.firestore()
.doc('posts/posts1')
.delete()
.then(() => {
// Document deleted
});
```
### Batching document updates
Writes, updates and deletes to documents can be batched and committed atomically as follows:
```javascript
import firebase from 'react-native-firebase';
const ayRef = firebase.firestore().doc('places/AY');
const lRef = firebase.firestore().doc('places/LON');
const nycRef = firebase.firestore().doc('places/NYC');
const sfRef = firebase.firestore().doc('places/SF');
firebase.firestore()
.batch()
.set(ayRef, { name: 'Aylesbury' })
.set(lRef, { name: 'London' })
.set(nycRef, { name: 'New York City' })
.set(sfRef, { name: 'San Francisco' })
.update(nycRef, { population: 1000000 })
.update(sfRef, { name: 'San Fran' })
.set(lRef, { population: 3000000 }, { merge: true })
.delete(ayRef)
.commit()
.then(() => {
// Would end up with three documents in the collection: London, New York City and San Francisco
});
```
### Transactions
Coming soon
## Realtime Updates
### Collections
Listen to collection updates example:
```javascript
import firebase from 'react-native-firebase';
firebase.firestore()
.collection('cities')
.where('state', '==', 'CA')
.onSnapshot((querySnapshot) => {
querySnapshot.forEach((doc) => {
// DocumentSnapshot available
})
})
```
The snapshot handler will receive a new query snapshot every time the query results change (that is, when a document is added, removed, or modified).
### Documents
Listen to document updates example:
```javascript
import firebase from 'react-native-firebase';
firebase.firestore()
.doc('posts/post1')
.onSnapshot((documentSnapshot) => {
// DocumentSnapshot available
})
```
The snapshot handler will receive the current contents of the document, and any subsequent changes to the document.

View File

@ -1,123 +0,0 @@
# Dynamic Links
[Firebase Dynamic Links](https://firebase.google.com/docs/dynamic-links/) allows you to create and receive links on both Android and iOS platforms. Assuming the installation instructions have been followed, Firebase Dynamic Links is ready to go.
All Dynamic Links operations are accessed via `firebase.links()`
## Create Dynamic Links
RNFirebase mimics [Firebase's REST API](https://firebase.google.com/docs/dynamic-links/rest) for Dynamic Links creation.
The differences from the REST API are:
1. The input for the methods is a javascript object instead of a JSON object.
2. The response contains the URL string only.
3. There is no `dynamicLinkInfo` element. Instead, all of the elements under it were moved to be under the top-level.
### Methods
#### `createDynamicLink(parameters: Object): Promise<String>`
Creates a long dynamic link.
```javascript
firebase.links().createDynamicLink({
dynamicLinkDomain: "abc123.app.goo.gl",
link: "https://example.com?param1=foo&param2=bar",
androidInfo: {
androidPackageName: "com.example.android"
},
iosInfo: {
iosBundleId: "com.example.ios"
}
}).
then((url) => {
// ...
});
```
#### `createShortDynamicLink(parameters: Object): Promise<String>`
Creates a short dynamic link.
```javascript
firebase.links().createShortDynamicLink({
dynamicLinkDomain: "abc123.app.goo.gl",
link: "https://example.com?param1=foo&param2=bar",
androidInfo: {
androidPackageName: "com.example.android"
},
iosInfo: {
iosBundleId: "com.example.ios"
}
}).
then((url) => {
// ...
});
```
### Parameters
Only the following parameters are currently supported:
```javascript
{
dynamicLinkDomain: 'string',
link: 'string',
androidInfo: {
androidPackageName: 'string',
androidFallbackLink: 'string',
androidMinPackageVersionCode: 'string',
androidLink: 'string',
},
iosInfo: {
iosBundleId: 'string',
iosFallbackLink: 'string',
iosCustomScheme: 'string',
iosIpadFallbackLink: 'string',
iosIpadBundleId: 'string',
iosAppStoreId: 'string',
},
socialMetaTagInfo: {
socialTitle: 'string',
socialDescription: 'string',
socialImageLink: 'string',
},
suffix: {
option: 'string',
},
}
```
**please note:**
1. dynamicLinkDomain and link are mandatory fields. In addition, when using `androidInfo` or `iosInfo`, `androidPackageName` and `iosBundleId` are mandatory (respectively).
2. In oppose to the REST API, There is no `dynamicLinkInfo` element. Instead, all of the elements under it were moved to be under the top-level.
For more information [see reference](https://firebase.google.com/docs/reference/dynamic-links/link-shortener)
## Receive Dynamic Links
### Methods
#### `getInitialLink(): Promise<String>`
Call getInitialLink to access the URL that the app has been launched from. If the app was not launched from a URL, the return value is null.
```javascript
firebase.links().getInitialLink().then((url) => {
//...
});
```
#### `onLink(listener: Function<String>): Function`
On a new URL, the payload URL is passed to the listener callback. This method is only triggered when the app is running. Use getInitialLink for URLs which cause the app to open.
In order to subscribe to the listener, call to the method with a callback and save the returned function.
When you want to unsubscribe, just call the function that returned at subscription.
```javascript
// Subscribe
const unsubscribe = firebase.links().onLink((url) => {
//...
});
// Unsubscribe
unsubscribe();
```

View File

@ -1,64 +0,0 @@
# Performance Monitoring
?> Android: If you plan on using this module in your own application, please ensure the optional setup instructions for
[Android](http://invertase.io/react-native-firebase/#/installation-android?id=_4-performance-monitoring-optional) have been followed.
Out of the box, [Firebase Performance Monitoring](https://firebase.google.com/docs/perf-mon/automatic) monitors a number of
[automatic traces](https://firebase.google.com/docs/perf-mon/automatic) such as app start/background/foreground response times.
You can easily trace your own events with RNFirebase:
## API
#### setPerformanceCollectionEnabled(enabled: `boolean`)
Globally enables or disables performance monitoring capture across the app.
```js
firebase.perf().setPerformanceCollectionEnabled(false); // Disable
```
#### newTrace(id: `string`): `Trace`
Returns a new instance of Trace (see API below). The id is the unique name of something you'd like to run performance
monitoring against.
```js
const trace = firebase.perf().newTrace("test_trace");
```
### Trace
!> Once a trace has been started and stopped, you cannot re-start it in the same app lifecycle.
#### start()
Initializes the trace to start tracing performance to relay back to Firebase.
```js
trace.start();
```
#### incrementCounter(event: string)
Notifies Firebase an event has occured. These events will be visible on Firebase once your trace has stopped.
```js
someCacheService.get('user:123')
.then((user) => {
if (user) {
trace.incrementCounter('user_cache_hit');
} else {
trace.incrementCounter('user_cache_missed');
}
});
```
#### stop()
Stops performance tracing. The completed trace stats are now sent to Firebase.
?> Results are not realtime. They can take a number of hours to appear in the Firebase console.
```js
trace.stop();
```

View File

@ -1,100 +0,0 @@
# Storage
RNFirebase mimics the [Web Firebase SDK Storage](https://firebase.google.com/docs/storage/web/start), whilst
providing some iOS and Android specific functionality.
## Uploading files
### Simple
```javascript
firebase.storage()
.ref('/files/1234')
.putFile('/path/to/file/1234')
.then(uploadedFile => {
//success
})
.catch(err => {
//Error
});
```
### With metadata
```javascript
const metadata = {
contentType: 'image/jpeg'
}
firebase.storage()
.ref('/files/1234')
.putFile('/path/to/file/1234', metadata)
```
### Listen to upload state
```javascript
const unsubscribe = firebase.storage()
.ref('/files/1234')
.putFile('/path/to/file/1234')
.on('state_changed', snapshot => {
//Current upload state
}, err => {
//Error
unsubscribe();
}, uploadedFile => {
//Success
unsubscribe();
});
```
## Downloading files
### Simple
```javascript
firebase.storage()
.ref('/files/1234')
.downloadFile('/path/to/save/file')
.then(downloadedFile => {
//success
})
.catch(err => {
//Error
});
```
### Listen to download state
```javascript
const unsubscribe = firebase.storage()
.ref('/files/1234')
.downloadFile('/path/to/save/file')
.on('state_changed', snapshot => {
//Current download state
}, err => {
//Error
unsubscribe();
}, downloadedFile => {
//Success
unsubscribe();
});
```
<!-- TODO -->
There are a few methods which have not yet been implemented for Storage:
### Reference
- put()
- putString()
### UploadTask
- cancel()
- pause()
- resume()
### DownloadTask
- cancel()
- pause()
- resume()

View File

@ -1,34 +0,0 @@
# Transactions
?> For help on how to use firebase transactions please see the [Firebase Transaction Documentation](https://firebase.google.com/docs/reference/js/firebase.database.Reference#transaction).
### Android Implementation
The [android implementation](https://github.com/invertase/react-native-firebase/blob/master/android/src/main/java/io/invertase/firebase/database/RNFirebaseTransactionHandler.java) makes use of [Condition](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Condition.html) and [ReentrantLock](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantLock.html) locks to handle transactions across the React Native Bridge.
### iOS Implementation
The [iOS implementation](https://github.com/invertase/react-native-firebase/blob/master/ios/RNFirebase/RNFirebaseDatabase.m#L279) makes use of GCD (Grand Central Dispatch) to handle transactions across the React Native Bridge without blocking the application thread. Check out [this](https://mikeash.com/pyblog/friday-qa-2011-10-14-whats-new-in-gcd.html) post for some 'light' reading about it.
!> Transactions that receive no response from react native's JS thread within 30 seconds are automatically aborted - this value is currently not configurable - PR welcome.
## Example
```javascript
const ref = firebase.database().ref('user/posts');
ref.transaction((posts) => {
return (posts || 0) + 1;
}, (error, committed, snapshot) => {
if (error) {
console.log('Something went wrong', error);
} else if (!committed) {
console.log('Aborted'); // Returning undefined will trigger this
} else {
console.log('User posts incremented by 1');
}
console.log('User posts is now: ', snapshot.val());
});
```

View File

@ -1,334 +0,0 @@
# Usage with Redux
Although RNFirebase usage requires a React Native environment, it isn't tightly coupled which allows for full flexibility
when it comes to integrating with other modules such a [`react-redux`](https://github.com/reactjs/react-redux).
## Standalone Integration
Although the following example works for a basic redux setup, it may differ when integrating with other redux middleware.
Imagine a simple TODO app, with redux we're able to abstract the Firebase logic out of components which allows for greater
testability and maintainability.
?> We use [`redux-thunk`](https://github.com/gaearon/redux-thunk) to provide async actions.
### Action Creators
```js
// Actions
export const subscribe = () => {
return (dispatch) => {
firebase.database().ref('todos').on('value', (snapshot) => {
const todos = [];
snapshot.forEach((childSnapshot) => {
todos.push({
id: childSnapshot.key,
...(childSnapshot.val()),
})
})
dispatch({
type: 'TODO_UPDATE',
todos,
})
})
}
}
// Methods
export const addTodo = text => {
firebase.database().ref('todos').push({
text,
visible: true,
})
}
export const completeTodo = id => {
firebase.database().ref(`todos/${id}`).update({
visible: false,
})
}
```
Instead of creating multiple actions which the reducers handle, we instead subscribe to the database ref and on any changes,
send a single action for the reducers to handle with the data which is constantly updating.
### Reducers
Our reducer now becomes really simple, as we're able to simply update the reducers state with whatever data has been returned
from our Firebase subscription.
```js
const todos = (state = {}, action) => {
switch (action.type) {
case 'TODO_UPDATE':
return { ...action.todos };
}
return state;
}
export default todos;
```
### Component
We can now easily subscribe to the todos in redux state and get live updates when Firebase updates.
```js
import React from 'react';
import { FlatList } from 'react-native';
import { connect } from 'react-redux';
import { subscribe, addTodo, completeTodo } from '../actions/TodoActions.js';
...
class Todos extends React.Component {
componentDidMount() {
this.props.dispatch(
subscribe()
);
}
onComplete = (id) => {
this.props.dispatch(
completeTodo(id)
);
};
onAdd = (text) => {
this.props.dispatch(
addTodo(text)
);
};
render() {
return (
<FlatList
data={this.props.todos}
...
/>
);
}
}
function mapStateToProps(state) {
return {
todos: state.todos,
};
}
export default connect(mapStateToProps)(Todos);
```
## React Redux Firebase
[`react-redux-firebase`](http://docs.react-redux-firebase.com/history/v2.0.0) provides simplified and standardized common redux/firebase logic.
To add `react-redux-firebase` to your project:
1. Make sure you already have `redux`, `react-redux`, `redux-thunk` installed (if not, run `npm i --save redux react-redux redux-thunk`)
1. Run `npm i --save react-redux-firebase@canary` *we point to canary here to get current progress with v2.0.0*
1. Add `firebaseStateReducer` under `firebase` key within reducer:
**reducers.js**
```js
import { combineReducers } from 'redux';
import { firebaseStateReducer } from 'react-redux-firebase';
export const makeRootReducer = (asyncReducers) => {
return combineReducers({
// Add sync reducers here
firebase: firebaseStateReducer,
...asyncReducers
});
};
export default makeRootReducer;
// *Optional* Useful for injecting reducers as part of async routes
export const injectReducer = (store, { key, reducer }) => {
store.asyncReducers[key] = reducer
store.replaceReducer(makeRootReducer(store.asyncReducers))
};
```
1. Pass `react-native-firebase` App instance into `reactReduxFirebase` when creating store:
**createStore.js**
```js
import { applyMiddleware, compose, createStore } from 'redux';
import RNFirebase from 'react-native-firebase';
import { getFirebase, reactReduxFirebase } from 'react-redux-firebase';
import thunk from 'redux-thunk';
import makeRootReducer from './reducers';
const reactNativeFirebaseConfig = {
debug: true
};
// for more config options, visit http://docs.react-redux-firebase.com/history/v2.0.0/docs/api/compose.html
const reduxFirebaseConfig = {
userProfile: 'users', // save users profiles to 'users' collection
};
export default (initialState = { firebase: {} }) => {
// initialize firebase
const firebase = RNFirebase.initializeApp(reactNativeFirebaseConfig);
const store = createStore(
makeRootReducer(),
initialState,
compose(
reactReduxFirebase(firebase, reduxFirebaseConfig), // pass initialized react-native-firebase app instance
// applyMiddleware(...middleware) // if using middleware
)
);
return store;
};
```
1. Wrap in `Provider` from `react-redux`:
**index.js**
```js
import React from 'react';
import { Provider } from 'react-redux';
import createStore from './createStore';
import Home from './Home';
// Store Initialization
const initialState = { firebase: {} };
let store = createStore(initialState);
const Main = () => (
<Provider store={store}>
<Home />
</Provider>
);
export default Main;
```
1. Then you can use the `firebaseConnect` HOC to wrap your components. It makes it easy to set listeners which gather data from Firebase and place it into redux:
**Home.js**
```js
import React from 'react';
import { compose } from 'redux';
import { connect } from 'react-redux';
import { isLoaded, isEmpty, firebaseConnect } from 'react-redux-firebase';
import { View, Text, StyleSheet, ActivityIndicator } from 'react-native';
import NewTodo from './NewTodo';
import Todos from './Todos';
class Home extends React.Component {
state = {
text: null
}
completeTodo = (key, todo) => {
return this.props.firebase.update(`todos/${key}`, { done: !todo.done })
}
addTodo = () => {
const { text } = this.state;
return this.props.firebase.push('todos', { text, completed: false });
}
render() {
const { todos } = this.props;
return (
<View>
<Text>Todos</Text>
<NewTodo
onNewTouch={this.addTodo}
newValue={this.state.text}
onInputChange={(v) => this.setState({text: v})}
/>
{
!isLoaded(todos)
? <ActivityIndicator size="large" style={{ marginTop: 100 }}/>
: null
}
{
isLoaded(todos) && !isEmpty(todos)
?
<Todos
todos={todos}
onItemTouch={this.completeTodo}
/>
:
<View style={styles.container}>
<Text>No Todos Found</Text>
</View>
}
</View>
);
}
}
export default compose(
firebaseConnect([
// create listener for firebase data -> redux
{ path: 'todos', queryParams: ['limitToLast=15'] }
]),
connect((state) => ({
// todos: state.firebase.data.todos, // todos data object from redux -> props.todos
todos: state.firebase.ordered.todos, // todos ordered array from redux -> props.todos
}))
)(Home);
```
**Todos.js**
```js
import React from 'react'
import {
View,
Text,
StyleSheet,
FlatList,
TouchableHighlight
} from 'react-native';
const Todos = ({ todos, onItemTouch }) => (
<FlatList
data={todos.reverse()}
renderItem={({ item: { key, value } }) => (
<TouchableHighlight onPress={() => onItemTouch(key, value)}>
<View>
<Text>{value.text}</Text>
<Text>Done: {value.done === true ? 'True' : 'False'}</Text>
</View>
</TouchableHighlight>
)}
/>
)
export default Todos;
```
Notice how `connect` is still used to get data out of `redux` since `firebaseConnect` only loads data **into** redux.
Full source with styling available [in the react-native-firebase example for react-redux-firebase](https://github.com/prescottprue/react-redux-firebase/tree/v2.0.0/examples/complete/react-native-firebase)
For more details, please visit [`react-redux-firebase`'s react-native section](http://docs.react-redux-firebase.com/history/v2.0.0/docs/recipes/react-native.html#native-modules).
#### Thunks
`react-redux-firebase` provides the `getFirebase` helper for easy access to Firebase helper methods. Using this feature is as easy as passing it in while creating your store:
```js
const middleware = [
// make getFirebase available in third argument of thunks
thunk.withExtraArgument({ getFirebase }),
];
const store = createStore(
makeRootReducer(),
initialState,
compose(
reactReduxFirebase(firebase, reduxFirebaseConfig),
applyMiddleware(...middleware) // pass in middleware
)
);
```

View File

@ -1,75 +0,0 @@
const RUNTIME = 'docsify'
const HOSTNAME_WHITELIST = [
self.location.hostname,
'fonts.gstatic.com',
'fonts.googleapis.com',
'unpkg.com'
]
// The Util Function to hack URLs of intercepted requests
const getFixedUrl = (req) => {
var now = Date.now()
var url = new URL(req.url)
// 1. fixed http URL
// Just keep syncing with location.protocol
// fetch(httpURL) belongs to active mixed content.
// And fetch(httpRequest) is not supported yet.
url.protocol = self.location.protocol
// 2. add query for caching-busting.
// Github Pages served with Cache-Control: max-age=600
// max-age on mutable content is error-prone, with SW life of bugs can even extend.
// Until cache mode of Fetch API landed, we have to workaround cache-busting with query string.
// Cache-Control-Bug: https://bugs.chromium.org/p/chromium/issues/detail?id=453190
if (url.hostname === self.location.hostname) {
url.search += (url.search ? '&' : '?') + 'cache-bust=' + now
}
return url.href
}
/**
* @Lifecycle Activate
* New one activated when old isnt being used.
*
* waitUntil(): activating ====> activated
*/
self.addEventListener('activate', event => {
event.waitUntil(self.clients.claim())
})
/**
* @Functional Fetch
* All network requests are being intercepted here.
*
* void respondWith(Promise<Response> r)
*/
self.addEventListener('fetch', event => {
// Skip some of cross-origin requests, like those for Google Analytics.
if (HOSTNAME_WHITELIST.indexOf(new URL(event.request.url).hostname) > -1) {
// Stale-while-revalidate
// similar to HTTP's stale-while-revalidate: https://www.mnot.net/blog/2007/12/12/stale
// Upgrade from Jake's to Surma's: https://gist.github.com/surma/eb441223daaedf880801ad80006389f1
const cached = caches.match(event.request)
const fixedUrl = getFixedUrl(event.request)
const fetched = fetch(fixedUrl, { cache: 'no-store' })
const fetchedCopy = fetched.then(resp => resp.clone())
// Call respondWith() with whatever we get first.
// If the fetch fails (e.g disconnected), wait for the cache.
// If theres nothing in cache, wait for the fetch.
// If neither yields a response, return offline pages.
event.respondWith(
Promise.race([fetched.catch(_ => cached), cached])
.then(resp => resp || fetched)
.catch(_ => { /* eat any errors */ })
)
// Update the cache with the version we fetched (only for ok status)
event.waitUntil(
Promise.all([fetchedCopy, caches.open(RUNTIME)])
.then(([response, cache]) => response.ok && cache.put(event.request, response))
.catch(_ => { /* eat any errors */ })
)
}
})

View File

@ -1,27 +0,0 @@
# Usage
After creating a Firebase project and installing the library, you can then use it in your project by importing the library in your JavaScript code:
```javascript
import firebase from 'react-native-firebase';
```
As the default app is pre-initialized natively there is no need to call `initializeApp` for the default app instance. Just import and go:
```javascript
import firebase from 'react-native-firebase';
firebase.auth().signInAnonymously()
.then((user) => {
console.log(user.isAnonymous);
});
```
### Configure Default App Instance
See [configure the default app instance](/core/config-default-app).
### Configuring RNFirebase
See [configure RNFirebase](/core/config-rnfirebase).

View File

@ -1,58 +0,0 @@
<div style="text-align: center;">
[![npm version](https://img.shields.io/npm/v/react-native-firebase.svg?style=flat-square)](https://www.npmjs.com/package/react-native-firebase)
[![NPM downloads](https://img.shields.io/npm/dm/react-native-firebase.svg?style=flat-square)](https://www.npmjs.com/package/react-native-firebase)
[![Package Quality](https://npm.packagequality.com/shield/react-native-firebase.svg?style=flat-square)](http://packagequality.com/#?package=react-native-firebase)
[![License](https://img.shields.io/npm/l/react-native-firebase.svg?style=flat-square)](/LICENSE)
[![Chat](https://img.shields.io/badge/chat-on%20discord-7289da.svg?style=flat-square)](https://discord.gg/t6bdqMs)
[![Donate](https://img.shields.io/badge/Donate-Patreon-green.svg?style=flat-square)](https://www.patreon.com/invertase)
</div>
---
RNFirebase is a _light-weight_ layer sitting on-top of the native Firebase libraries for both iOS and Android which mirrors the Firebase Web SDK as closely as possible.
Although the [Firebase Web SDK](https://www.npmjs.com/package/firebase) library will work with React Native, it is mainly built for the web.
RNFirebase provides a JavaScript bridge to the native Firebase SDKs for both iOS and Android therefore Firebase will run on the native thread, allowing the rest of your app to run on the [JS thread](https://facebook.github.io/react-native/docs/performance.html#javascript-frame-rate). The Firebase Web SDK also runs on the JS thread, therefore potentially affecting the frame rate causing jank with animations, touch events etc.
The native SDKs also allow us to hook into device sdk's which are not possible with the web SDK, for example crash reporting, offline realtime database support, analyics and more!
All in all, RNFirebase provides much faster performance (~2x) over the web SDK and provides device sdk's not found in the web sdk (see the feature table below).
---
## Supported Firebase Features
> The Web SDK column indicates what modules from the Firebase Web SDK are usable within React Native.
| Firebase Features | v1 | v2 | Web SDK |
| ---------------------- | :---: | :---: | :---: |
| AdMob | ❌ | ✅ | ❌ |
| Analytics             | ✅ | ✅ | ❌ |
| App Indexing           | ❌ | ❌ | ❌ |
| Authentication | ✅ | ✅ | ✅ |
| Cloud Messaging (FCM) | ✅ | ✅ | ❌ |
| Crash Reporting | ✅ | ✅ | ❌ |
| Dynamic Links | ❌ | ❌ | ❌ |
| Invites | ❌ | ❌ | ❌ |
| Performance Monitoring | ✅ | ✅ | ❌ |
| Realtime Database | ✅ | ✅ | ✅ |
| - Offline Persistence | ✅ | ✅ | ❌ |
| - Transactions | ✅ | ✅ | ✅ |
| Remote Config | ✅ | ✅ | ❌ |
| Storage | ✅ | ✅ | ❌ |
---
### Supported versions - React Native / Firebase
> The table below shows the supported version of `react-native-firebase` for different React Native versions
| | v0.36 - v0.39 | v0.40 - v0.46 | v0.47 +
| ------------------------------- | :---: | :---: | :---: |
| react-native-firebase | 1.X.X | 2.X.X | 2.1.X |
> The table below shows the minimum supported versions of the Firebase SDKs for each version of `react-native-firebase`
| | v1 | v2 |
| ---------------------- | :---: | :---: |
| Firebase Android SDK | 10.2.0+ | 11.0.0 + |
| Firebase iOS SDK | 3.15.0+ | 4.0.0 + |

View File

@ -1,3 +0,0 @@
- <div class="version-select"><b>Version:</b> v2.x.x</div>
- [v3.x.x](/)

View File

@ -1,31 +0,0 @@
- ![#f03c15](https://placehold.it/15/f03c15/000000?text=+) Viewing old RNFirebase version ![#f03c15](https://placehold.it/15/f03c15/000000?text=+)
- Getting started
- [Initial setup](/v2/initial-setup)
- [Installation - iOS](/v2/installation-ios)
- [Installation - Android](/v2/installation-android)
- [Usage](/v2/usage)
- [Migration Guide](/v2/migration-guide)
- Contributing
- [Guidelines](/v2/contributing/guidelines)
- [Testing](/v2/contributing/testing)
- Modules
- [Admob](/v2/modules/admob)
- [Analytics](/v2/modules/analytics)
- [Authentication](/v2/modules/authentication)
- [Cloud Messaging](/v2/modules/cloud-messaging)
- [Crash Reporting](/v2/modules/crash)
- [Database](/v2/modules/database)
- [Remote Config](/v2/modules/config)
- [Storage](/v2/modules/storage)
- [Transactions](/v2/modules/transactions)
- [Performance Monitoring](/v2/modules/perf)
- Other
- [Usage with Redux](/v2/redux)
- [Project Board](https://github.com/invertase/react-native-firebase/projects)
- [FAQs / Troubleshooting](/v2/faqs)
- [Examples](https://github.com/invertase/react-native-firebase-examples)
- [Chat](https://discord.gg/t6bdqMs)

View File

@ -1,5 +0,0 @@
# Guidelines
We welcome any contribution to the repository. Please ensure your changes to the JavaScript code follow the styling guides controlled by ESlint. Changes to native code should be kept clean and follow the standard of existing code.
Changes to existing code should ensure all relevant tests on the test app pass. Any new features should have new tests created and ensure all existing tests pass.

View File

@ -1,330 +0,0 @@
# Testing
Currently due to the blackbox Firebase enviroment, we have found the best way to test the library is to directly test against the library using a live Firebase project. As some modules also work with the offical web SDK, we can directly compare the results against our own library. This is however restrictive as it doesn't directly test the native code/modules. Plans are in place to overhaul the entire testing setup.
## Running the test app
For convenience all of the required NPM scripts are packaged with the main library to run the test app.
### Step 1 - Fork & Clone
```bash
git clone git@github.com:<username>/react-native-firebase.git
```
### Step 2 - Install dependencies
```bash
npm run tests-npm-install
```
### Step 3 - Install [WML](https://github.com/wix/wml)
WML is a library which copies files & directories to a location. This allows us to copy any changes from the library directly into the tests app, so we can quickly test changes.
```bash
npm install -g wml
```
### Step 4 - Start the watcher
```bash
npm run tests-watch-init
npm run tests-watch-start
```
### Step 5 - Start the app
```bash
npm run tests-packager
```
#### Android
Open the `tests/android` directory from Android Studio and allow Gradle to sync. Now run the app on an emulator/device.
#### iOS
First install the Pods:
```
npm run tests-pod-install
```
Open the `tests/ios/ReactNativeFirebaseDemo.xcworkspace` file in XCode and build for your preffered device or simulator.
## Tests
Tests are bootstrapped and ran when the `play` button is pressed. The status of each test suite and individual test will update as and when a test has completed or errored.
### Running tests
Tests can be run by pressing the play button in the toolbar of the app. Test can be run individually, by suite, or all at once.
![Test suite Android](https://github.com/invertase/react-native-firebase/blob/master/tests/docs/assets/test-suite-screenshot-android.png?raw=true)
### Adding test
To add tests to an existing test suite, you need to pass a function to `addTests`.
#### Synchronous tests
Synchronous tests are created by passing a function to `it`. The next test is run immediately after the last line is executed.
```javascript
testSuite.addTests(({ describe, it }) => {
describe('synchronous test', () => {
it('does something correctly', () => {
});
});
});
```
#### Asynchronous tests
Tests can be asynchronous if they return a promise. The test suite waits for the promise to resolve before executing the next test.
```javascript
testSuite.addTests(({ describe, it }) => {
describe('async successful test', () => {
it('does something correctly', () => {
return new Promise((resolve, reject) => {
// ...
resolve();
});
});
});
});
```
Asynchronous tests can also be created using the `async` function syntax:
```javascript
testSuite.addTests(({ describe, it }) => {
describe('async successful test', () => {
it('does something correctly', async () => {
// ...
await somethingAsynchronous();
});
});
});
```
> When rejecting, always ensure a valid [JavaScript Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) is provided.
### Creating a new test suite
A test suite groups together test categories under the same Firebase feature. e.g. *Realtime Database* tests.
To add a new test suite:
1. Create a new directory within `src/tests`.
2. Create an `index.js` file.
In this file, you need to create an instance of `TestSuite` - see [TestSuite constructor](#testsuite-constructor).
```javascript
import TestSuite from 'lib/TestSuite';
const MyNewSuite = new TestSuite('Realtime Database Storage', 'Upload/Download storage tests');
export default MyNewSuite;
```
3. `addTests` is then used as many times as is necessary to add tests to the test suite, accepting a function that defines one or more tests.
4. The test suite must then be imported into `src/tests/index.js` and added to `testSuiteInstances` in order for it to be included in the list of test suites available to run in the app.
## TestSuite API
### TestSuite Constructor
The TestSuite constructor accepts 3 arguments:
- **name**: String containing the name of the test suite. e.g. 'Realtime Storage'
- **description**: String containing description of the test suite
- **firebase**: This is the object exported from `src/firebase` and contains both the native and web firebase instances.
```javascript
import firebase from '../firebase';
new TestSuite('Realtime Database Storage', 'firebase.database()', firebase);
```
### Test Definition
#### describe()
The `describe()` function takes 2 - 3 arguments:
- **description**: String describing the context or target of all the tests defined in `testDefinitions`
- **options**: (Optional) object of options:
* **focus**: Boolean marking all the tests defined in `testDefinitions` (and any others marked as focused) as the only one(s) that should run
* **pending**: Boolean marking all the tests defined in `testDefinitions` as excluded from running in the test suite
- **testDefinitions**: Function that defines 1 or more tests by calling `it`, `xit` or `fit`
```javascript
function testCategory({ describe }) {
describe('a feature', () => {
it('does something synchronously', () => {
});
});
}
export default testCategory;
```
`describe()` statements can be arbitrarily nested.
#### context()
`context()` is an alias for `describe()` provided as syntactical sugar. `xcontext()` and `fcontext()` work similar to `xdescribe()` and `fdescribe()`, respectively.
#### it()
The `it()` function takes 2 - 3 arguments:
- **description**: String describing the test defined in `testDefinition`
- **options**: (Optional) object of options:
* **focus**: Boolean marking the test defined in `testDefinition` (and any others marked as focused) as the only one(s) that should run
* **pending**: Boolean marking the test defined in `testDefinition` as excluded from running in the test suite
* **timeout**: Time in milliseconds a test is allowed to execute before it's considered to have timed out. Default is 5000ms (5 seconds).
- **testDefinition**: Function that defines a test with one or more assertions. Can be a synchronous or asynchronous function. Functions that return a promise cause the test environment to wait for the promise to be resolved before proceding to the next test.
```javascript
it('does something synchronously', () => {
});
it('does something asynchronously', async () => {
});
it('does something else asynchronously', () => {
return new Promise(/* ... */);
});
```
`it()` statements can *not* be nested.
#### xdescribe() & xit()
##### Pending Tests
You can mark all tests within a `describe` statement as pending by using the `xdescribe` function instead. The test will appear greyed out and will not be run as part of the test suite.
You can mark a single test as pending by using `xit` as you would `it`.
Tests should only be marked as pending temporarily, and should not normally be committed to the test suite unless they are fully implemented.
#### fdescribe() & fit()
##### Focused Tests
You can mark all tests within a `describe` statement as focused by using the `fdescribe` function instead. Tests that are focused will be the only ones that appear and run in the test suite until all tests are removed from being focused. This is useful for running and working on a few tests at a time.
You can mark a single test as focused by using `fit` as you would `it`.
#### Test Assertions
The assertion library Should.js is used in the tests. The complete list of available assertions is available in the [Should.js documentation](https://shouldjs.github.io).
#### Lifecycle methods
Four lifecycle methods are provided for each test context:
- **before** - Run once, before the current test context executes
- **beforeEach** - Run before every test in the current test context
- **after** - Run once, after the current test context has finished executing
- **afterEach** - Run after every test in the current test context
A new test context is created when the test suite encounters any of `describe`, `xdescribe`, `fdescribe`, `context`, `xcontext` or `fcontext`, and close again when it reaches the end of the block. Test contexts can be nested and lifecycle hooks set for parent contexts apply for all descendents.
Each lifecycle hook accepts either a synchronous function, a function that returns a promise or an `async` function.
```javascript
function testCategory({ before, beforeEach, afterEach, after }) {
before(() => console.log('Before all tests start.'));
beforeEach(() => console.log('Before every test starts.'));
describe('sync successful test', function() {
// ...
});
afterEach(() => console.log('After each test starts.'));
after(() => console.log('After all tests are complete, with success or error.'));
}
```
An optional hash of options can also be passed as the first argument, defining one or more of the following values:
* **timeout**: Time in milliseconds a hook is allowed to execute before it's considered to have timed out. Default is 5000ms (5 seconds).
#### Accessing Firebase
`react-native-firebase` is available `firebase.native`:
```javascript
function testCategory({ describe, firebase }) {
describe('sync successful test', 'category', function() {
firebase.native.database();
});
}
```
If you need to access the web API for Firebase to compare with the functionality of `react-native-firebase`, you can access it on `firebase.web`.
> All tests should be written in terms of `react-native-firebase`'s behaviour and should **not** include direct comparisons with the web API. It's available for reference, only.
## Development Notes
> JavaScript changes do **not** require restarting the React Native packager to take effect
> Java changes will need to be rebuilt in Android Studio
> Objective-C changes need to be rebuilt in Xcode
### Debugging or viewing internals of the test suite
`react-native-firebase/tests` is compatible with [react-native-debugger](https://github.com/jhen0409/react-native-debugger) and is the recommended way to view the internal state of the test suite for development or troubleshooting.
It allows you to view state and prop values of the React component tree, view the actions and contents of the Redux store and view and interact with the debugging console.
Make sure **Remote JS Debugging** when running the application and close any chrome debugging windows that appear and start React Native Debugger.
### Running the internal tests
`react-native-firebase-tests` has its own tests to verify the testing framework is working as expected. These are run from the command line:
```bash
npm run internal-tests
```
## Troubleshooting
### Invalid React.podspec file: no implicit conversion of nil into String
This error occurs if you are using ruby version 2.1.2. Upgrade your version of ruby and try again.
### Unable to resolve module ../../../node_modules/react-native/packager/...
Run the packager separately, clearing the cache:
```bash
npm start -- --reset-cache
```

View File

@ -1,103 +0,0 @@
# FAQs / Troubleshooting
## Usage with Expo
If you use Expo and would like to use this package, you'll need to eject. If you do not want to eject, but wish to make use of features
such as Realtime Database (without offline support) & Authentication, you can still use the Firebase Web SDK in your project.
For features such a Crash Reporting, Push Notifications (via Firebase not Expo), Performance Monitoring, AdMob, Analytics, Storage & Remote Config, you will have to eject your Expo project as these require the native SDKs, as the Web SDK does not support these.
You can see an indepth conversation [here](https://expo.canny.io/feature-requests/p/full-native-firebase-integration).
## Comparison to Firestack
Firestack was a great start to integrating Firebase and React Native, however has underlying issues which needed to be fixed.
A V3 fork of Firestack was created to help address issues such as lack of standardisation with the Firebase Web SDK,
and missing core features (crash reporting, transactions etc). The volume of pull requests with fixes/features soon became
too large to manage on the existing repository, whilst trying to maintain backwards compatibility.
RNFirebase was re-written from the ground up, addressing these issues with core focus being around matching the Web SDK as
closely as possible and fixing the major bugs/issues along the way.
## [Android] Google Play Services related issues
The firebase SDK requires a certain version of Google Play Services installed on Android in order to function properly.
If the version of Google Play Services installed on your device is incorrect or non existent, React Native Firebase will throw a red box error, and your app will possibly crash as well. The red box error will have a numerical code associated with it. These codes can be found here:
https://developers.google.com/android/reference/com/google/android/gms/common/ConnectionResult#SERVICE_VERSION_UPDATE_REQUIRED
Here is a quick guide to some of the most common errors encountered:
code 2 - Google Play Services is required to run this application but no valid installation was found:
The emulator/device you're using does not have the Play Services SDK installed.
- Emulator: Open SDK manager, under 'SDK Tools' ensure "Google Play services, rev X" is installed. Once installed,
create a new emulator image. When selecting your system image, ensure the target comes "with Google APIs".
- Device: Play Services needs to be downloaded from the Google Play Store.
code 9 - The version of the Google Play services installed on this device is not authentic:
This error applies to modified or 'shimmed' versions of Google Play Services which you might be using in a third
party emulator such as GenyMotion.
Using this kind of workaround with Google Play Services can be problematic, so we
recommend using the native Android Studio emulators to reduce the chance of these complications.
## [Android] Turning off Google Play Services availability errors
G.P.S errors can be turned off using a config option like so:
```javascript
const firebase = RNFirebase.initializeApp({
errorOnMissingPlayServices: false,
});
```
This will stop your app from immediately red-boxing or crashing, but won't solve the underlying issue of G.P.S not being available or of the correct version. This will mean certain functionalities won't work properly and your app may even crash.
## [Android] Checking for Google Play Services availability with React Native Firebase
React Native Firebase actually has a useful helper object for checking G.P.S availability:
```javascript
const availability = firebase.googleApiAvailability;
```
The availability object would then have the following properties that you can run checks against:
```javascript
isAvailable: boolean
```
and if not available (isAvailable === false):
```javascript
isUserResolvableError: boolean
```
This variable indicates whether or not the end user can fix the issue, for example by downloading the required version of Google Play Services. In a case such as a GenyMotion emulator, this would return false for missing G.P.S, as the end user can't add the package directly.
```javascript
error: string
```
This error will match the messages and error codes mentioned above, and can be found here:
https://developers.google.com/android/reference/com/google/android/gms/common/ConnectionResult#SERVICE_VERSION_UPDATE_REQUIRED
## [Android] Duplicate Dex Files error (build time error)
A common build time error when using libraries that require google play services is of the form:
'Failed on android with com.android.dex.DexException: Multiple dex files... '
This error (https://github.com/invertase/react-native-firebase/issues/48) occurs because different versions of google play services or google play services modules are being required by different libraries.
The process to fix this is fairly manual and depends on your specific combination of external libraries. Essentially what's required is to check the app level build.gradle file of each external library and establish which ones have a Google Play Services dependency.
You then need to find the lowest common version of each G.P.S module dependency, require that in the app level build.gradle file of your own project, and exclude it from being required by the modules themselves. This will force the use of a consistent version of the G.P.S module.
It's not a good idea to modify the version within the library's build.gradle, as this will be overwritten when you update the library, which will lead to the build breaking again.
A good break down of this process can be found here:
https://medium.com/@suchydan/how-to-solve-google-play-services-version-collision-in-gradle-dependencies-ef086ae5c75f

View File

@ -1,21 +0,0 @@
# Install the library
`npm install --save react-native-firebase`
# Initial Setup
The RNFirebase library is intended on making it easy to work with [Firebase](https://firebase.google.com/) and provides a small native shim to the Firebase native code.
To add Firebase to your project, make sure to create a project in the [Firebase console](https://firebase.google.com/console)
![Create a new project](https://i.imgur.com/KbbamwD.png)
Each platform uses a different setup method after creating the project.
## iOS
For iOS, follow the instructions [here](/installation-ios).
## Android
For Android, follow the instructions [here](/installation-android).

View File

@ -1,183 +0,0 @@
# Android Installation
## 1) Setup google-services.json
Download the `google-services.json` file provided by Firebase in the _Add Firebase to Android_ platform menu in your Firebase configuration console. This file should be downloaded to `YOUR_PROJECT/android/app/google-services.json`.
Next you'll have to add the google-services gradle plugin in order to parse it.
Add the google-services gradle plugin as a dependency in the *project* level build.gradle
`android/build.gradle`
```java
buildscript {
// ...
dependencies {
// ...
classpath 'com.google.gms:google-services:3.0.0'
}
}
```
In your app build.gradle file, add the gradle plugin at the VERY BOTTOM of the file (below all dependencies)
`android/app/build.gradle`
```java
apply plugin: 'com.google.gms.google-services'
```
## 2) Link RNFirebase
RNFirebase is split into separate modules to allow you to only include the Firebase functionality that you need in your application.
First add the project path to `android/settings.gradle`:
```
include ':react-native-firebase'
project(':react-native-firebase').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-firebase/android')
```
Now you need to include RNFirebase and the required Firebase dependencies in our `android/app/build.gradle` so that they are compiled as part of React Native. In the `dependencies` listing, add the appropriate `compile` lines:
```
dependencies {
// RNFirebase required dependencies
compile(project(':react-native-firebase')) {
transitive = false
}
compile "com.google.firebase:firebase-core:11.0.4"
// If you are receiving Google Play API availability issues, add the following dependency
compile "com.google.android.gms:play-services-base:11.0.4"
// RNFirebase optional dependencies
compile "com.google.firebase:firebase-ads:11.0.4"
compile "com.google.firebase:firebase-auth:11.0.4"
compile "com.google.firebase:firebase-config:11.0.4"
compile "com.google.firebase:firebase-crash:11.0.4"
compile "com.google.firebase:firebase-database:11.0.4"
compile "com.google.firebase:firebase-messaging:11.0.4"
compile "com.google.firebase:firebase-perf:11.0.4"
compile "com.google.firebase:firebase-storage:11.0.4"
}
```
To install `react-native-firebase` in your project, you'll need to import the packages you need from `io.invertase.firebase` in your project's `android/app/src/main/java/com/[app name]/MainApplication.java` and list them as packages for ReactNative in the `getPackages()` function:
```java
package com.youcompany.application;
// ...
// Required package
import io.invertase.firebase.RNFirebasePackage; // <-- Add this line
// Optional packages - add as appropriate
import io.invertase.firebase.admob.RNFirebaseAdMobPackage; //Firebase AdMob
import io.invertase.firebase.analytics.RNFirebaseAnalyticsPackage; // Firebase Analytics
import io.invertase.firebase.auth.RNFirebaseAuthPackage; // Firebase Auth
import io.invertase.firebase.config.RNFirebaseRemoteConfigPackage; // Firebase Remote Config
import io.invertase.firebase.crash.RNFirebaseCrashPackage; // Firebase Crash Reporting
import io.invertase.firebase.database.RNFirebaseDatabasePackage; // Firebase Realtime Database
import io.invertase.firebase.messaging.RNFirebaseMessagingPackage; // Firebase Cloud Messaging
import io.invertase.firebase.perf.RNFirebasePerformancePackage; // Firebase Performance
import io.invertase.firebase.storage.RNFirebaseStoragePackage; // Firebase Storage
// ...
public class MainApplication extends Application implements ReactApplication {
// ...
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new RNFirebasePackage(), // <-- Add this line
// Add these packages as appropriate
new RNFirebaseAdMobPackage(),
new RNFirebaseAnalyticsPackage(),
new RNFirebaseAuthPackage(),
new RNFirebaseRemoteConfigPackage(),
new RNFirebaseCrashPackage(),
new RNFirebaseDatabasePackage(),
new RNFirebaseMessagingPackage(),
new RNFirebasePerformancePackage(),
new RNFirebaseStoragePackage()
);
}
};
// ...
}
```
## 3) Cloud Messaging (optional)
If you plan on using [Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging/), add the following to `android/app/src/main/AndroidManifest.xml`.
Add permissions:
```xml
<manifest ...>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.VIBRATE" />
```
Set app [launch mode](https://inthecheesefactory.com/blog/understand-android-activity-launchmode/en) inside activity props:
```xml
<activity
...
android:launchMode="singleTop"
>
```
Add messaging service:
```xml
<application ...>
<service
android:name="io.invertase.firebase.messaging.MessagingService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service android:name="io.invertase.firebase.messaging.InstanceIdService" android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
```
If you would like to schedule local notifications then you also need to add the following:
```xml
<receiver android:name="io.invertase.firebase.messaging.RNFirebaseLocalMessagingPublisher"/>
<receiver android:enabled="true" android:exported="true" android:name="io.invertase.firebase.messaging.RNFirebaseSystemBootEventReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
```
## 4) Performance Monitoring (optional)
If you'd like to take advantage of Firebase's [Performance Monitoring](https://firebase.google.com/docs/perf-mon/), the following additions
to your project setup are required:
In your projects `android/build.gradle` file, add the plugin to your dependencies:
```
dependencies {
...
classpath 'com.google.firebase:firebase-plugins:1.1.0'
}
```
At the top of your `android/app/build.gradle` file, below other plugins, apply the `firebase-perf` plugin:
```
apply plugin: "com.android.application"
apply plugin: "com.google.firebase.firebase-perf"
```
In the same file, add the `firebase-perf` module to your dependencies:
```
dependencies {
...
compile "com.google.firebase:firebase-perf:11.0.4"
}
```

View File

@ -1,163 +0,0 @@
# iOS Installation
Please note that there is a known issue when using Cocoapods with the `use_frameworks!` enabled. This is explained [here](https://github.com/invertase/react-native-firebase/issues/252#issuecomment-316340974). Unfortunately we don't currently have a workaround, but are engaging with Firebase directly to try and resolve the problem.
## 1) Setup GoogleService-Info.plist
Setup the `GoogleService-Info.plist` file by following the instructions and adding it to the root of your project at `ios/[YOUR APP NAME]/GoogleService-Info.plist` [here](https://firebase.google.com/docs/ios/setup#add_firebase_to_your_app).
### 1.1) Initialisation
Make sure you've added the following to the top of your `ios/[YOUR APP NAME]]/AppDelegate.m` file:
`#import <Firebase.h>`
and this to the `didFinishLaunchingWithOptions:(NSDictionary *)launchOptions` method before the `return` statement:
`[FIRApp configure];`
## 2) Setup RNFirebase
Unfortunately, due to the fact that Firebase is much easier to setup using Cocoapods, *we do not recommend* `react-native link` as it is not customisable enough for our needs and we have had numerous problems reported.
### 2.0) If you don't already have Cocoapods set up
Follow the instructions to install Cocoapods and create your Podfile [here](https://firebase.google.com/docs/ios/setup#add_the_sdk).
**NOTE: The Podfile needs to be initialised in the `ios` directory of your project. Make sure to update cocoapods libs first by running `pod update`**
#### Troubleshooting
1) When running `pod install` you may encounter an error saying that a `tvOSTests` target is declared twice. This appears to be a bug with `pod init` and the way that react native is set up.
**Resolution:**
- Open your Podfile
- Remove the duplicate `tvOSTests` target nested within the main project target
- Re-run `pod install`.
2) When running `pod install` you may encounter a number of warnings relating to `target overrides 'OTHER_LDFLAGS'`.
**Resolution:**
- Open Xcode
- Select your project
- For each target:
-- Select the target
-- Click Build settings
-- Search for `other linker flags`
-- Add `$(inherited)` as the top line if it doesn't already exist
- Re-run `pod install`
3) When running `pod install` you may encounter a warning that a default iOS platform has been assigned. If you wish to specify a different minimum version:
**Resolution**
- Open your Podfile
- Uncomment the `# platform :ios, '9.0'` line by removing the `#` character
- Change the version as required
### 2.1) Add the required pods
Simply add the following to your `Podfile` either at the top level, or within the main project target:
```ruby
# Required by RNFirebase
pod 'Firebase/Core'
pod 'RNFirebase', :path => '../node_modules/react-native-firebase'
# [OPTIONAL PODS] - comment out pods for firebase products you won't be using.
pod 'Firebase/AdMob'
pod 'Firebase/Auth'
pod 'Firebase/Crash'
pod 'Firebase/Database'
pod 'Firebase/DynamicLinks'
pod 'Firebase/Messaging'
pod 'Firebase/RemoteConfig'
pod 'Firebase/Storage'
```
If you do not already have React and Yoga installed as pods, then add Yoga and React to your `Podfile` as follows:
```ruby
pod "Yoga", :path => "../node_modules/react-native/ReactCommon/yoga"
pod 'React', :path => '../node_modules/react-native', :subspecs => [
'BatchedBridge', # Required For React Native 0.45.0+
'Core',
# Add any other subspecs you want to use in your project
]
```
Run `pod install`.
**NOTE: You need to use the `ios/[YOUR APP NAME].xcworkspace` instead of the `ios/[YOUR APP NAME].xcproj` file from now on.**
#### Troubleshooting
1) You receive an error `No podspec found for 'RNFirebase'`
**Resolution**
- Run `npm install --save react-native-firebase` from the root of your project
## 3) Cloud Messaging (optional)
If you plan on using [Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging/) then, you need to:
**NOTE: FCM does not work on the iOS simulator, you must test is using a real device. This is a restriction enforced by Apple for some unknown reason.**
### 3.1) Set up certificates
Follow the instructions at https://firebase.google.com/docs/cloud-messaging/ios/certs
### 3.2) Enable capabilities
In Xcode, enable the following capabilities:
1) Push Notifications
2) Background modes > Remote notifications
### 3.3) Update `AppDelegate.h`
Add the following import:
`@import UserNotifications;`
Change the interface descriptor to:
`@interface AppDelegate : UIResponder <UIApplicationDelegate,UNUserNotificationCenterDelegate>`
### 3.4) Update `AppDelegate.m`
Add the following import:
`#import "RNFirebaseMessaging.h"`
Add the following to the `didFinishLaunchingWithOptions:(NSDictionary *)launchOptions` method after `[FIRApp Configure]`:
`[[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];`
Add the following methods:
```objectivec
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
[RNFirebaseMessaging didReceiveLocalNotification:notification];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo {
[RNFirebaseMessaging didReceiveRemoteNotification:userInfo];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo
fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler{
[RNFirebaseMessaging didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
[RNFirebaseMessaging willPresentNotification:notification withCompletionHandler:completionHandler];
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)())completionHandler {
[RNFirebaseMessaging didReceiveNotificationResponse:response withCompletionHandler:completionHandler];
}
```
### 3.5) Debugging
If you're having problems with messages not being received, check out the following blog post for help:
https://firebase.googleblog.com/2017/01/debugging-firebase-cloud-messaging-on.html

View File

@ -1,172 +0,0 @@
# Migration
## From v1 to v2
The below is a quick summary of steps to take when migrating from v1 to v2 of RNFirebase. Please see the [v2 change log](https://github.com/invertase/react-native-firebase/releases/tag/v2.0.0) for detailed changes.
##### 1) Install the latest version of RNFirebase:
> `npm i react-native-firebase@latest --save`
##### 2) Upgrade react-native version (only if you're currently lower than v0.40):
> For example: `npm i react-native@0.44.0 react@16.0.0-alpha.6 --save`
##### 3) Update your JS code to reflect deprecations/breaking changes:
- [deprecated] providerId should now be used instead of provider whilst obtaining auth credentials. The latter will be removed in future releases.
- [deprecated] Deprecated User.getToken in favour of User.getIdToken.
- [breaking] User.reauthenticate has been removed in favour of User.reauthenticateWithCredential.
- [breaking] User.link has been removed in favour of User.linkWithCredential.
- [breaking] Removed unnecessary didReceiveNotificationResponse and willPresentNotification methods for iOS messaging. Added additional didReceiveRemoteNotification method.
- [breaking] firebase.messaging().onTokenRefresh and firebase.messaging().onMessage return a function to unsubscribe as per the Web SDK spec: https://firebase.google.com/docs/reference/js/firebase.messaging.Messaging#onMessage. Previously they returned an object with a .remove() method.
##### 4) Android - Update `android/build.gradle`:
The latest google-services version needs to be used:
```groovy
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.3'
classpath 'com.google.gms:google-services:3.0.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
```
##### 5) Android - Update `app/build.gradle`:
All firebase modules are now optional so you only need to import the Firebase functionality that you require in your application.
You need to make a couple of changes to your `app/build.gradle` file. Update the react-native-firebase compile statement to read:
```groovy
compile(project(':react-native-firebase')) {
transitive = false
}
compile "com.google.firebase:firebase-core:11.0.4"
// If you are receiving Google Play API availability issues, add the following dependency
compile "com.google.android.gms:play-services-base:11.0.4"
```
Add each of the firebase modules you need from the following list:
```groovy
compile "com.google.firebase:firebase-ads:11.0.4"
compile "com.google.firebase:firebase-auth:11.0.4"
compile "com.google.firebase:firebase-config:11.0.4"
compile "com.google.firebase:firebase-crash:11.0.4"
compile "com.google.firebase:firebase-database:11.0.4"
compile "com.google.firebase:firebase-messaging:11.0.4"
compile "com.google.firebase:firebase-perf:11.0.4"
compile "com.google.firebase:firebase-storage:11.0.4"
```
##### 6) Android - Update `MainApplication.java`:
Update `MainApplication.java` and import the modules you require / currently use:
```java
// Required package
import io.invertase.firebase.RNFirebasePackage; // <-- Keep this line
// Optional packages - add as appropriate
import io.invertase.firebase.admob.RNFirebaseAdMobPackage; // Firebase AdMob
import io.invertase.firebase.analytics.RNFirebaseAnalyticsPackage; // Firebase Analytics
import io.invertase.firebase.auth.RNFirebaseAuthPackage; // Firebase Auth
import io.invertase.firebase.config.RNFirebaseRemoteConfigPackage; // Firebase Remote Config
import io.invertase.firebase.crash.RNFirebaseCrashPackage; // Firebase Crash Reporting
import io.invertase.firebase.database.RNFirebaseDatabasePackage; // Firebase Realtime Database
import io.invertase.firebase.messaging.RNFirebaseMessagingPackage; // Firebase Cloud Messaging
import io.invertase.firebase.perf.RNFirebasePerformancePackage; // Firebase Performance Monitoring
import io.invertase.firebase.storage.RNFirebaseStoragePackage; // Firebase Storage
```
Add the packages to the `getPackages()` method as required:
```java
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new RNFirebasePackage(), // <-- Keep this line
// Add these packages as appropriate
new RNFirebaseAdMobPackage(),
new RNFirebaseAnalyticsPackage(),
new RNFirebaseAuthPackage(),
new RNFirebaseRemoteConfigPackage(),
new RNFirebaseCrashPackage(),
new RNFirebaseDatabasePackage(),
new RNFirebaseMessagingPackage(),
new RNFirebasePerformancePackage(),
new RNFirebaseStoragePackage()
);
}
```
##### 7) iOS - Update podfile:
First, delete your `Podfile.lock` file, and after making any changes from the below re-run `pod install` in your ios directory.
As all firebase modules are now optional you only need to import the Firebase functionality that you require in your application. Simply update your Podfile to only include the Firebase modules for functionality that you require in your app.
For example if you only use Auth and Storage in your app then your podfile would look like the below:
```ruby
install! 'cocoapods', :deterministic_uuids => false
# Uncomment this line to define a global platform for your project
# platform :ios, '9.0'
target 'ReactNativeFirebaseDemo' do
platform :ios, '8.0'
# Uncomment this line if you're using Swift or would like to use dynamic frameworks
# use_frameworks!
react_native_path = "../node_modules/react-native"
pod "Yoga", :path => "#{react_native_path}/ReactCommon/yoga"
pod 'React', :path => '#{react_native_path}', :subspecs => [
'BatchedBridge', # Required For React Native 0.45.0+
'Core',
# Add any other subspecs you want to use in your project
# ...
]
# Core is always required
pod 'Firebase/Core'
# Optional modules
pod 'Firebase/Auth'
pod 'Firebase/Storage'
pod 'RNFirebase', :path => '../node_modules/react-native-firebase'
end
```

View File

@ -1,382 +0,0 @@
# AdMob
The admob allows you to display adverts in your app, using your account from [AdMob by Google](https://www.google.co.uk/admob/). RNFirebase allows you to display Banners, Interstitials, NativeExpress Ads & Rewarded Videos.
## Initialize
Before using any AdMob feature, ensure you call the initialize method. This only needs to be done once per the apps lifecycle.
Initialize takes your AdMob App ID, where you can find on your AdMob dashboard.
> For testing purposes, you can use AdMobs test app ID "ca-app-pub-3940256099942544~3347511713".
```js
firebase.admob().initialize("ca-app-pub-3940256099942544~3347511713");
```
## Debugging
Once initialized, you can debug ((Android)[https://developers.google.com/mobile-ads-sdk/docs/dfp/android/debug]/(iOS)[https://developers.google.com/mobile-ads-sdk/docs/dfp/ios/debug])
your ads using the debug menu.
```js
firebase.admob().openDebugMenu();
```
## API
### Banner
AdMob Banners in RNFirebase are exported as a usable React component, allowing you to integrate it easily into your existing app very easily.
#### Props
| Prop | Type | Default | Description |
| ------------------- | ------------------ | --------------------------------------- | ----------------------------------------------------------------------------------- |
| size | string (See Sizes) | SMART_BANNER | Returns a sized banner (automatically sets View style) |
| unitId | string | | Your AdMob banner unit ID. |
| request | AdRequest | new AdRequest().addTestDevice().build() | An instance of AdRequest to load with the Banner |
| onAdLoaded | function | | Called when an ad is received. |
| onAdOpened | function | | Called when an ad opens an overlay that covers the screen. |
| onAdLeftApplication | function | | Called when an ad leaves the application (e.g., to go to the browser). |
| onAdClosed | function | | Called when the user is about to return to the application after clicking on an ad. |
| onAdFailedToLoad | function | | Called when an ad request failed. See Error Handling |
#### Example
```js
const Banner = firebase.admob.Banner;
const AdRequest = firebase.admob.AdRequest;
const request = new AdRequest();
request.addKeyword('foobar');
...
render() {
return (
<Banner
size={"LARGE_BANNER"}
request={request.build()}
onAdLoaded={() => {
console.log('Advert loaded and is now visible');
}}
/>
);
}
```
### Interstitial
An interstitial is a full screen advert which creates a new activity on top of React. As they need to be controlled,
allowing the developer to choose when to display them they're not available as a component. Instead they're controlled via
method calls.
A single interstitial instance can only be shown once. If you want to display another, create a new one.
To request an interstitial from AdMob, the `loadAd` method must be called with an instance of `AdRequest` (see below for full API):
#### Methods
| Method | Description |
| ------------------- | ---------------------------------------------------------------------------- |
| loadAd(AdRequest) | Loads an advert with request config |
| on(event, callback) | Listens to advert events. See Event Types for more information. |
| isLoaded() | Returns a boolean value as to whether the advert is loaded and ready to show.|
| show() | Show the advert on the device |
#### Example
```js
const advert = firebase.admob().interstitial('ca-app-pub-3940256099942544/1033173712');
const AdRequest = firebase.admob.AdRequest;
const request = new AdRequest();
request.addKeyword('foo').addKeyword('bar');
// Load the advert with our AdRequest
advert.loadAd(request.build());
advert.on('onAdLoaded', () => {
console.log('Advert ready to show.');
});
// Simulate the interstitial being shown "sometime" later during the apps lifecycle
setTimeout(() => {
if (advert.isLoaded()) {
advert.show();
} else {
// Unable to show interstitial - not loaded yet.
}
}, 1000);
```
### Native Express
An AdMob Native Express advert is much like a standard Banner, except it can be integrated seamlessly into your app using user predefined
styling (background color, positions, font size etc). Native Express adverts are exported as a usable React component.
#### Props
| Prop | Type | Default | Description |
| ------------------- | ------------------ | --------------------------------------- | ----------------------------------------------------------------------------------- |
| size | string (See Sizes) | SMART_BANNER | TODO |
| unitId | string | | Your AdMob banner unit ID. |
| request | AdRequest | new AdRequest().addTestDevice().build() | An instance of AdRequest to load with the Banner |
| video | AdRequest | new VideoOptions().build() | An instance of AdRequest to load with the Banner |
| onAdLoaded | function | | Called when an ad is received. |
| onAdOpened | function | | Called when an ad opens an overlay that covers the screen. |
| onAdLeftApplication | function | | Called when an ad leaves the application (e.g., to go to the browser). |
| onAdClosed | function | | Called when the user is about to return to the application after clicking on an ad. |
| onAdFailedToLoad | function | | Called when an ad request failed. See Event PropTypes for more information. |
| onVideoEnd | function | | Called if the advert video has ended (only called if the advert has a video). |
#### Usage
```js
const Banner = firebase.admob.Banner;
const NativeExpress = firebase.admob.NativeExpress;
const AdRequest = firebase.admob.AdRequest;
const request = new AdRequest();
request.addKeyword('foobar');
...
render() {
return (
<NativeExpress
size={"300x400"}
request={request.build()}
onAdLoaded={() => {
console.log('Advert loaded and is now visible');
}}
/>
);
}
```
### Rewarded Video
A rewarded video allows you to display a video to a user, whereby they're able to watch it to gain "rewards", or skip it
and receive nothing. For example, when a user completes a level on your gaming app, show them a video which will give them in-game
credit.
A single rewarded video instance can only be shown once. If you want to display another, create a new one.
?> It's recommended you begin loading the video as soon as possible.
To request an Rewarded Video from AdMob, the `loadAd` method must be called with an instance of `AdRequest` (see below for full API):
#### Methods
| Method | Description |
| ------------------- | ---------------------------------------------------------------------------- |
| loadAd(AdRequest) | Loads an advert with request config |
| on(event, callback) | Listens to advert events. See Event Types |
| isLoaded() | Returns a boolean value as to whether the advert is loaded and ready to show |
| show() | Show the advert on the device |
#### Example
```js
const advert = firebase.admob().rewarded('ca-app-pub-3940256099942544/1033173712');
const AdRequest = firebase.admob.AdRequest;
const request = new AdRequest();
request.addKeyword('foo').addKeyword('bar');
// Load the advert with our AdRequest
advert.loadAd(request.build());
advert.on('onAdLoaded', () => {
console.log('Advert ready to show.');
});
advert.on('onRewarded', (event) => {
console.log('The user watched the entire video and will now be rewarded!', event);
});
...
onLevelComplete()
.then(() => {
if (advert.isLoaded()) {
advert.show();
} else {
// skip...
}
});
```
### AdRequest
The AdRequest class is used to create an object to be passed to each advert request. The request is handled on AdMob,
and returns adverts tailored to the request options provided.
!> If no AdRequest is sent, the default request calls `addTestDevice`. Therefore, ensure a custom AdRequest object is passed through
in production.
##### build()
Builds the current request for AdMob to handle.
##### addTestDevice(device?: string)
Sets a device ID as a test device. If no device string is passed, a default emulator id is passed.
##### addKeyword(keyword: `string`)
Add a new keyword to relate the advert to.
##### setBirthday(date: `Date`)
Sets the user's birthday for targeting purposes.
##### setGender(gender: `male | female | unknown`)
Sets the user's gender for targeting purposes.
##### setLocation()
Sets the user's location for targeting purposes.
##### setRequestAgent(requestAgent: `string`)
Sets the request agent string to identify the ad request's origin. Third party libraries that reference the Mobile Ads SDK should call this method to denote the platform from which the ad request originated. For example, if a third party ad network called "CoolAds network" mediates requests to the Mobile Ads SDK, it should call this method with "CoolAds"
##### setContentUrl(url: `string`)
Sets the content URL for targeting purposes.
##### [android] setIsDesignedForFamilies(forFamilies: `boolean`)
If you set this value to true, you indicate that your app requires that the ad request should return a Designed for Families-compliant ad.
If you set this value to false, you indicate that your app does not require that the ad request should return a Designed for Families-compliant ad.
##### tagForChildDirectedTreatment(forChildren: `boolean`)
### VideoOptions
The VideoOptions class is used to create an object to be passed through to each advert request. If the advert returns a video,
the options are used when displaying it on the application.
?> Currently `NativeExpress` only accepts VideoOptions. If no VideoOptions are sent, the default options call `setStartMuted(true)`.
##### build()
Builds the current options for AdMob to handle.
##### setStartMuted(muted: `boolean`)
If true, any returned video will not play sound when it starts. The end user can manually enable sound on the advert interface.
## Prop Types
##### size: `String`
Sets the size of an Advert. Can be one of the following or a custom size:
| Size | Description |
| ----------------- | ------------------------------------------------------------------------------------------------------ |
| BANNER | Mobile Marketing Association (MMA) banner ad size (320x50 density-independent pixels). |
| FULL_BANNER | Interactive Advertising Bureau (IAB) full banner ad size (468x60 density-independent pixels). |
| LARGE_BANNER | Large banner ad size (320x100 density-independent pixels). |
| LEADERBOARD | Interactive Advertising Bureau (IAB) leaderboard ad size (728x90 density-independent pixels). |
| MEDIUM_RECTANGLE | Interactive Advertising Bureau (IAB) medium rectangle ad size (300x250 density-independent pixels). |
| SMART_BANNER | A dynamically sized banner that is full-width and auto-height. |
To specify a custom size, pass a string with the width and height split by an "x" (follows the Regex pattern `([0-9]+)x([0-9]+)`), e.g 320x150
?> Requesting an advert with a size which does not exist on the AdMob servers will return `admob/error-code-internal-error`.
##### unitId: `String`
The unit ID for the banner. Defaults to the testing unitId provided by Google for the advert type.
##### request: `AdRequest`
A built AdRequest object returned from `AdRequest.build()`.
##### video: `VideoOptions`
A built VideoOptions object returned from `VideoOptions.build()`.
### Events
Every advert returns common event types. On component based adverts (e.g. Banner) they're available as props and on instance based
adverts (e.g. Interstitial) they're available via the `on` method.
##### onAdLoaded(config: `Object`)
!> The config is not provided for Interstitial or Rewarded Video adverts.
On successful response from the AdMob servers. This is also called when a new banner is automatically loaded from the AdMob servers if the current one expires.
Returns an object of config data related to the loaded advert:
```js
{
hasVideoContent: boolean,
width: number,
height: number,
}
```
##### onAdOpened()
Called when the user presses the advert and it successfully opens.
##### onAdLeftApplication()
Called if the opened advert causes the user to leave the application, for example opening a URL in the browser.
##### onAdClosed()
Called when the user returns back to the application after closing an advert.
##### onAdFailedToLoad(error: `Error`)
Called when an advert fails to load. Returns a JavaScript Error with one of the following error codes.
| code | message |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| admob/error-code-internal-error | Something happened internally; for instance, an invalid response was received from the ad server. |
| admob/error-code-invalid-request | The ad request was invalid; for instance, the ad unit ID was incorrect. |
| admob/error-code-network-error | The ad request was unsuccessful due to network connectivity. |
| admob/error-code-no-fill | The ad request was successful, but no ad was returned due to lack of ad inventory. |
| admob/os-version-too-low | The current devices OS is below the minimum required version. |
##### [NativeExpress] onVideoEnd()
Called when video playback finishes playing.
##### [NativeExpress] onVideoMute(config: `Object`)
Called when the video changes mute state.
```js
{
isMuted: boolean,
}
```
##### [NativeExpress] onVideoPause()
Called when video playback is paused.
##### [NativeExpress] onVideoPlay()
Called when video playback is playing.
##### [NativeExpress] onVideoStart()
alled when video playback first begins.
##### [RewardedVideo] onRewarded(reward: `Object`)
Called when the user has been rewarded (usually for watching an entire video). Returns a reward object:
```js
{
type: string,
amount: number,
}
```
##### [RewardedVideo] onRewardedVideoStarted()
Called when a rewarded video has started to play.
## Statics
The following statics are available on the `firebase.admob` instance.
### Banner
Exports a React component to display an AdMob Banner.
### NativeExpress
Exports a React component to display an AdMob Native Express advert.
### AdRequest
Used to build a request object to pass into AdMob requests.
### VideoOptions
Used to build an options object for how videos should be handled with adverts containing a video.
### EventTypes
Returns all of the available advert event types.
### RewardedVideoEventTypes
Returns the extra event types for Rewarded Videos.
### NativeExpressEventTypes
Returns the extra event types for Native Express adverts.

View File

@ -1,90 +0,0 @@
# Analytics
Integrating Firebase analytics is simple. A number of methods are provided to help tailor analytics specifically for your
own app. The Firebase SDK includes a number of pre-set events which are automatically handled, and cannot be used with custom `logEvent` events:
```
'app_clear_data',
'app_uninstall',
'app_update',
'error',
'first_open',
'first_visit',
'first_open_time',
'first_visit_time',
'in_app_purchase',
'notification_dismiss',
'notification_foreground',
'notification_open',
'notification_receive',
'os_update',
'session_start',
'screen_view',
'user_engagement',
'ad_impression',
'ad_click',
'ad_query',
'ad_exposure',
'adunit_exposure',
'ad_activeiew',
```
#### `logEvent(event: string, params?: Object): void`
Log a custom event with optional params.
```javascript
firebase.analytics().logEvent('clicked_advert', { id: 1337 });
```
#### `setAnalyticsCollectionEnabled(enabled: boolean): void`
Sets whether analytics collection is enabled for this app on this device.
```javascript
firebase.analytics().setAnalyticsCollectionEnabled(false);
```
#### `setCurrentScreen(screenName: string, screenClassOverride?: string): void`
Sets the current screen name, which specifies the current visual context in your app.
> Whilst `screenClassOverride` is optional, it is recommended it is always sent as your current class name, for example on Android it will always show as 'MainActivity' if not specified.
```javascript
firebase.analytics().setCurrentScreen('user_profile');
```
#### `setMinimumSessionDuration(miliseconds: number): void`
Sets the minimum engagement time required before starting a session. The default value is 10000 (10 seconds).
```javascript
firebase.analytics().setMinimumSessionDuration(15000);
```
#### `setSessionTimeoutDuration(miliseconds: number): void`
Sets the duration of inactivity that terminates the current session. The default value is 1800000 (30 minutes).
```javascript
firebase.analytics().setSessionTimeoutDuration(900000);
```
#### `setUserId(id: string): void`
Gives a user a unique identification.
```javascript
const id = firebase.auth().currentUser.uid;
firebase.analytics().setUserId(id);
```
#### `setUserProperty(name: string, value: string): void`
Sets a key/value pair of data on the current user.
```javascript
firebase.analytics().setUserProperty('nickname', 'foobar');
```

View File

@ -1,324 +0,0 @@
# Authentication
RNFirebase handles authentication for us out of the box, both with email/password-based authentication and through oauth providers (with a separate library to handle oauth providers, see [examples](#examples)).
> Authentication requires Google Play services to be installed on Android.
## Auth
### Properties
##### `authenticated: boolean` - Returns the current Firebase authentication state.
##### `currentUser: User | null` - Returns the currently signed-in user (or null). See the [User](/modules/authentication.md#user) class documentation for further usage.
### Methods
#### [`onAuthStateChanged(event: Function): Function`](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#onAuthStateChanged)
Listen for changes in the users auth state (logging in and out). This method returns a unsubscribe function to stop listening to events. Always ensure you unsubscribe from the listener when no longer needed to prevent updates to components no longer in use.
```javascript
class Example extends React.Component {
constructor() {
super();
this.unsubscribe = null;
}
componentDidMount() {
this.unsubscribe = firebase.auth().onAuthStateChanged((user) => {
if (user) {
// User is signed in.
}
});
}
componentWillUnmount() {
if (this.unsubscribe) {
this.unsubscribe();
}
}
}
```
#### [`createUserWithEmailAndPassword(email: string, password: string): Promise`](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#createUserWithEmailAndPassword)
We can create a user by calling the `createUserWithEmailAndPassword()` function.
The method accepts two parameters, an email and a password.
```javascript
firebase.auth().createUserWithEmailAndPassword('foo@bar.com', '123456')
.then((user) => {
console.log('user created', user)
})
.catch((err) => {
console.error('An error occurred', err);
});
```
#### [`signInWithEmailAndPassword(email: string, password: string): Promise`](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#signInWithEmailAndPassword)
To sign a user in with their email and password, use the `signInWithEmailAndPassword()` function.
It accepts two parameters, the user's email and password:
```javascript
firebase.auth().signInWithEmailAndPassword('foo@bar.com', '123456')
.then((user) => {
console.log('User successfully logged in', user)
})
.catch((err) => {
console.error('User signin error', err);
});
```
#### [`signInAnonymously(): Promise`](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#signInAnonymously)
Sign an anonymous user. If the user has already signed in, that user will be returned.
```javascript
firebase.auth().signInAnonymously()
.then((user) => {
console.log('Anonymous user successfully logged in', user)
})
.catch((err) => {
console.error('Anonymous user signin error', err);
});
```
#### [`signInWithCredential(credential: Object): Promise`](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#signInWithCredential)
Sign in the user with a 3rd party credential provider. `credential` requires the following properties:
```javascript
{
provider: string,
token: string,
secret: string
}
```
```javascript
const credential = {
provider: 'facebook',
token: '12345',
secret: '6789',
};
firebase.auth().signInWithCredential(credential)
.then((user) => {
console.log('User successfully signed in', user)
})
.catch((err) => {
console.error('User signin error', err);
});
```
#### [`signInWithCustomToken(token: string): Promise`](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#signInWithCustomToken)
Sign a user in with a self-signed [JWT](https://jwt.io) token.
To sign a user using a self-signed custom token, use the `signInWithCustomToken()` function. It accepts one parameter, the custom token:
```javascript
firebase.auth().signInWithCustomToken('12345')
.then((user) => {
console.log('User successfully logged in', user)
})
.catch((err) => {
console.error('User signin error', err);
});
```
#### [`sendPasswordResetEmail(email: string): Promise`](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#sendPasswordResetEmail)
Sends a password reset email to the given email address. Unlike the web SDK, the email will contain a password reset link rather than a code.
```javascript
firebase.auth().sendPasswordResetEmail('foo@bar.com')
.then(() => {
console.log('Password reset email sent');
})
.catch((error) => {
console.error('Unable send password reset email', error);
});
```
#### [`signOut(): Promise`](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#confirmPasswordReset)
Completes the password reset process, given a confirmation code and new password.
```javascript
firebase.auth().signOut()
.then(() => {
console.log('User signed out successfully');
})
.catch();
```
## User
User class returned from `firebase.auth().currentUser`.
### Properties
##### `displayName: string | null` - The user's display name (if available).
##### `email: string | null` - The user's email address (if available).
##### `emailVerified: boolean` - True if the user's email address has been verified.
##### `isAnonymous: boolean`
##### `photoURL: string | null` - The URL of the user's profile picture (if available).
##### `providerData: Object | null` - Additional provider-specific information about the user.
##### `providerId: string | null` - The authentication provider ID for the current user. For example, 'facebook.com', or 'google.com'.
##### `uid: string` - The user's unique ID.
### Methods
#### [`delete(): Promise`](https://firebase.google.com/docs/reference/js/firebase.User#delete)
Delete the current user.
```javascript
firebase.auth().currentUser
.delete()
.then()
.catch();
```
#### [`getToken(): Promise`](https://firebase.google.com/docs/reference/js/firebase.User#getToken)
Returns the users authentication token.
```javascript
firebase.auth().currentUser
.getToken()
.then((token) => {})
.catch();
```
#### [`reauthenticate(credential: Object): Promise`](https://firebase.google.com/docs/reference/js/firebase.User#reauthenticate)
Reauthenticate the current user with credentials:
```javascript
{
provider: string,
token: string,
secret: string
}
```
```javascript
const credentials = {
provider: 'facebook',
token: '12345',
secret: '6789',
};
firebase.auth().currentUser
.reauthenticate(credentials)
.then()
.catch();
```
#### [`reload(): Promise`](https://firebase.google.com/docs/reference/js/firebase.User#reload)
Refreshes the current user.
```javascript
firebase.auth().currentUser
.reload()
.then((user) => {})
.catch();
```
#### [`sendEmailVerification(): Promise`](https://firebase.google.com/docs/reference/js/firebase.User#sendEmailVerification)
Sends a verification email to a user. This will Promise reject is the user is anonymous.
```javascript
firebase.auth().currentUser
.sendEmailVerification()
.then()
.catch();
```
#### [updateEmail(email: string)](https://firebase.google.com/docs/reference/js/firebase.User#updateEmail)
Updates the user's email address. See Firebase docs for more information on security & email validation. This will Promise reject is the user is anonymous.
```javascript
firebase.auth().currentUser
.updateEmail('foo@bar.com')
.then()
.catch();
```
#### [updatePassword(password: string)](https://firebase.google.com/docs/reference/js/firebase.User#updatePassword)
Important: this is a security sensitive operation that requires the user to have recently signed in. If this requirement isn't met, ask the user to authenticate again and then call firebase.User#reauthenticate. This will Promise reject is the user is anonymous.
```javascript
firebase.auth().currentUser
.updatePassword('foobar1234')
.then()
.catch();
```
#### [updateProfile(profile: Object)](https://firebase.google.com/docs/reference/js/firebase.User#updateProfile)
Updates a user's profile data. Profile data should be an object of fields to update:
```javascript
{
displayName: string,
photoURL: string,
}
```
```javascript
firebase.auth().currentUser
.updateProfile({
displayName: 'Display Name'
})
.then()
.catch();
```
## Examples
### Facebook authentication with react-native-fbsdk and signInWithCredential
```javascript
import { AccessToken, LoginManager } from 'react-native-fbsdk';
// ... somewhere in your login screen component
LoginManager
.logInWithReadPermissions(['public_profile', 'email'])
.then((result) => {
if (result.isCancelled) {
return Promise.resolve('cancelled');
}
console.log(`Login success with permissions: ${result.grantedPermissions.toString()}`);
// get the access token
return AccessToken.getCurrentAccessToken();
})
.then(data => {
// create a new firebase credential with the token
const credential = firebase.auth.FacebookAuthProvider.credential(data.accessToken);
// login with credential
return firebase.auth().signInWithCredential(credential);
})
.then((currentUser) => {
if (currentUser === 'cancelled') {
console.log('Login cancelled');
} else {
// now signed in
console.warn(JSON.stringify(currentUser.toJSON()));
}
})
.catch((error) => {
console.log(`Login fail with error: ${error}`);
});
```

View File

@ -1,145 +0,0 @@
# Cloud Messaging
Firebase Cloud Messaging ([FCM](https://firebase.google.com/docs/cloud-messaging/)) allows you to send push messages at no
cost to both Android & iOS platforms. Assuming the installation instructions have been followed, FCM is ready to go.
As the Firebase Web SDK has limited messaging functionality, the following methods within `react-native-firebase` have been
created to handle FCM in the React Native environment.
Badge notification is well known on the iOS platform, but also supported by different Android devices / launchers.
This library uses the [ShortcutBadger](https://github.com/leolin310148/ShortcutBadger) library to set the badge number
also on Android. A list of supported launcher can be found there.
!> [iOS] Please note: In order for iOS devices to receive Cloud Messages, ensure you [request permissions](http://invertase.io/react-native-firebase/#/modules/cloud-messaging?id=ios-requestpermissions).
## API
### subscribeToTopic(topic: string)
Subscribes the device to a topic.
```javascript
firebase.messaging().subscribeToTopic('foobar');
```
### unsubscribeFromTopic(topic: string)
Unsubscribes the device from a topic.
```javascript
firebase.messaging().unsubscribeFromTopic('foobar');
```
### getInitialNotification(): `Promise<Object>`
When the application has been opened from a notification `getInitialNotification` is called and the notification payload
is returned. Use `onMessage` for notifications when the app is running.
```javascript
firebase.messaging().getInitialNotification()
.then((notification) => {
console.log('Notification which opened the app: ', notification);
});
```
### getToken(): `Promise<string>`
Returns the devices FCM token. This token can be used in the Firebase console to send messages to directly.
```javascript
firebase.messaging().getToken()
.then((token) => {
console.log('Device FCM Token: ', token);
});
```
### onTokenRefresh(listener: `Function<string>`)
On the event a devices FCM token is refreshed by Google, the new token is returned in a callback listener.
```javascript
firebase.messaging().onTokenRefresh((token) => {
console.log('Refreshed FCM token: ', token);
});
```
### onMessage(listener: `Function<Object>`)
On a new message, the payload object is passed to the listener callback. This method is only triggered when the app is
running. Use `getInitialNotification` for notifications which cause the app to open.
```javascript
firebase.messaging().onMessage((message) => {
// TODO
});
```
### createLocalNotification(notification: Object)
Create a local notification from the device itself.
// TODO
### scheduleLocalNotification(notification: Object)
Schedule a local notification to be shown on the device.
### getScheduledLocalNotifications(): `Promise<Array>`
Returns an array of all currently scheduled notifications.
```javascript
firebase.messaging().getScheduledLocalNotifications()
.then((notifications) => {
console.log('Current scheduled notifications: ', notifications);
});
```
### cancelLocalNotification(id: string)
Cancels a location notification by ID, or all notifications by `*`.
```javascript
// Cancel all local notifications
firebase.messaging().cancelLocalNotification('*');
// Cancel a single local notification
firebase.messaging().cancelLocalNotification('123');
```
### removeDeliveredNotification(id: string)
Removes all delivered notifications from device by ID, or all notifications by `*`.
```javascript
// Remove all notifications
firebase.messaging().removeDeliveredNotification('*');
// Removes a single local notification
firebase.messaging().removeDeliveredNotification('123');
```
### [iOS] requestPermissions()
Requests app notification permissions in an Alert dialog.
```javascript
firebase.messaging().requestPermissions();
```
### setBadgeNumber(value: number)
Sets the badge number on the iOS app icon.
```javascript
firebase.messaging().setBadgeNumber(2);
```
### getBadgeNumber(): `Promise<number>`
Returns the current badge number on the app icon.
```javascript
firebase.messaging().getBadgeNumber()
.then((badgeNumber) => {
console.log('Current badge number: ', badgeNumber);
});
```

View File

@ -1,149 +0,0 @@
# Remote Config
?> Remote Config is not available on the web SDK. Please read the [documentation](https://firebase.google.com/docs/remote-config) on when & why Remote Config benefits your app.
## API
### enableDeveloperMode()
Enable Remote Config developer mode to allow for frequent refreshes of the cache.
```js
firebase.config().enableDeveloperMode();
```
### setDefaults(defaults: `Object`)
Sets default values for the app to use when accessing values. Any data fetched and activated will override any default values.
Any values in the defaults but not on Firebase will be untouched.
```js
firebase.config().setDefaults({
hasExperimentalFeature: false,
});
```
### fetch(duration?: `number`): `Promise<String>`
Fetches the remote config data from Firebase, defined in the dashboard.
If duration is defined (seconds), data will be locally cached for this duration.
The default duration is 43200 seconds (12 hours). To force a cache refresh call the method with a duration of 0.
Thrown errors can be one of the following:
* config/failure - Config fetch failed.
* config/no_fetch_yet - Config has never been fetched.
* config/throttled - Config fetch was throttled.
```js
firebase.config()
.fetch()
.then(() => {
console.log('Successfully fetched data');
})
.catch((error) => {
console.error('Unable to fetch remote config data: ', error);
});
```
### activateFetched(): `Promise<Boolean>`
Moves fetched data in the apps active config. Always successfully resolves with a boolean value.
```js
firebase.config()
.activateFetched()
.then((success) => {
if (success) {
console.log('Successfully activated fetched config into active config');
} else {
console.log('No fetched config was found or fetched config is already active');
}
});
```
### getValue(key: `String`): `Promise<Object>`
Gets a config item by key. Returns an object containing source (default, remote or static) and val function.
```js
firebase.config()
.getValue('foobar')
.then((snapshot) => {
console.log('Got value from source: ', snapshot.source);
console.log('Value of foobar: ', snapshot.val());
})
.catch(console.error);
```
### getValues(keys: `Array<String>`): `Promise<Object>`
Gets multiple values by key. Returns an object of keys with the same object returned from `getValue`.
```js
firebase.config()
.getValues(['foobar', 'barbaz'])
.then((snapshot) => {
console.log('Value of foobar: ', snapshot.foobar.val());
console.log('Value of barbaz: ', snapshot.barbaz.val());
})
.catch(console.error);
```
### getKeysByPrefix(prefix?: `String`): `Promise <Array<String>>`
Returns all keys as an array by a prefix. If no prefix is defined all keys are returned.
```js
firebase.config()
.getKeysByPrefix()
.then((keys) => {
console.log('Current keys: ', keys);
});
```
### setDefaultsFromResource(filename: `String`)
Sets the default values from a resource:
* Android: Id for the XML resource, which should be in your application's res/xml folder.
* iOS: The plist file name, with no file name extension
```js
// Anrdoid
firebase.config().setDefaultsFromResource(1337);
// iOS
firebase.config().setDefaultsFromResource('configDefaults');
```
## Usage
```js
if (__DEV__) {
firebase.config().enableDeveloperMode();
}
// Set default values
firebase.config().setDefaults({
hasExperimentalFeature: false,
});
firebase.config().fetch()
.then(() => {
return firebase.config().activateFetched();
})
.then((activated) => {
if (!activated) console.log('Fetched data not activated');
return firebase.config().getValue('hasExperimentalFeature');
})
.then((snapshot) => {
const hasExperimentalFeature = snapshot.val();
if(hasExperimentalFeature) {
// enableSuperCoolFeature();
}
// continue booting app
})
.catch(console.error);
```

View File

@ -1,54 +0,0 @@
# Crash Reporting
RNFirebase provides crash reporting for your app out of the box. Please note crashes do not appear in real-time on the console, they tend to take a number of hours to appear.
## Enabling/Disabling Crash Reporting
By default crash reporting is enabled. If you want to disable reporting, call `setCrashCollectionEnabled(enabled: Boolean)`:
```js
firebase.crash().setCrashCollectionEnabled(false);
```
To check if crash reporting is currently enabled, call `isCrashCollectionEnabled(): Promise<boolean>`:
```js
firebase.crash().isCrashCollectionEnabled()
.then((enabled) => {
if (enabled) {
console.log('Crash Reporting is currently enabled');
}
});
```
## Manual Crash Reporting
If you want to manually report a crash, such as a pre-caught exception this is possible by using the `report` method.
```javascript
try {
initSomeSDK();
} catch (e) {
firebase.crash().log('Some SDK failed to boot!');
firebase.crash().report(e);
}
```
### log
Logs a message that will appear in a subsequent crash report.
`firebase.crash().log(String message);`
### logcat
- **Android**: Logs a message that will appear in a subsequent crash report as well as in [logcat](https://developer.android.com/studio/command-line/logcat.html).
- **iOS**: Logs the message in the subsequest crash report only (same as `log`).
`firebase.crash().logcat(int level, String tag, String message);`
### report
Files a crash report, along with any previous logs to Firebase. An [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) object must be passed into the report method.
`firebase.crash().report(Error, int maxStackSize)`.

View File

@ -1,204 +0,0 @@
# Realtime Database
RNFirebase mimics the [Web Firebase SDK Realtime Database](https://firebase.google.com/docs/database/web/read-and-write), whilst
providing support for devices in low/no data connection state.
All real time Database operations are accessed via `database()`.
Basic read example:
```javascript
firebase.database()
.ref('posts')
.on('value', (snapshot) => {
const value = snapshot.val();
});
```
Basic write example:
```javascript
firebase.database()
.ref('posts/1234')
.set({
title: 'My awesome post',
content: 'Some awesome content',
});
```
## Unmounted components
Listening to database updates on unmounted components will trigger a warning:
> Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the undefined component.
It is important to always unsubscribe the reference from receiving new updates once the component is no longer in use.
This can be achived easily using [Reacts Component Lifecycle](https://facebook.github.io/react/docs/react-component.html#the-component-lifecycle) events:
Always ensure the handler function provided is of the same reference so RNFirebase can unsubscribe the ref listener.
```javascript
class MyComponent extends Component {
constructor() {
super();
this.ref = null;
}
// On mount, subscribe to ref updates
componentDidMount() {
this.ref = firebase.database().ref('posts/1234');
this.ref.on('value', this.handlePostUpdate);
}
// On unmount, ensure we no longer listen for updates
componentWillUnmount() {
if (this.ref) {
this.ref.off('value', this.handlePostUpdate);
}
}
// Bind the method only once to keep the same reference
handlePostUpdate = (snapshot) => {
console.log('Post Content', snapshot.val());
}
render() {
return null;
}
}
```
## Usage in offline environments
### Reading data
Firebase allows the database instance to [persist on disk](https://firebase.google.com/docs/database/android/offline-capabilities) if enabled.
To enable database persistence, pass the configuration option `persistence` before calls are made:
```javascript
const configurationOptions = {
persistence: true
};
const firebase = new RNFirebase(configurationOptions);
```
Any subsequent calls to Firebase stores the data for the ref on disk.
### Writing data
Out of the box, Firebase has great support for writing operations in offline environments. Calling a write command whilst offline
will always trigger any subscribed refs with new data. Once the device reconnects to Firebase, it will be synced with the server.
The following todo code snippet will work in both online and offline environments:
```javascript
// Assume the todos are stored as an object value on Firebase as:
// { name: string, complete: boolean }
class ToDos extends Component {
constructor() {
super();
this.ref = null;
this.listView = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2,
});
this.state = {
todos: this.listView.cloneWithRows({}),
};
// Keep a local reference of the TODO items
this.todos = {};
}
// Load the Todos on mount
componentDidMount() {
this.ref = firebase.database().ref('users/1234/todos');
this.ref.on('value', this.handleToDoUpdate);
}
// Unsubscribe from the todos on unmount
componentWillUnmount() {
if (this.ref) {
this.ref.off('value', this.handleToDoUpdate);
}
}
// Handle ToDo updates
handleToDoUpdate = (snapshot) => {
this.todos = snapshot.val() || {};
this.setState({
todos: this.listView.cloneWithRows(this.todos),
});
}
// Add a new ToDo onto Firebase
// If offline, this will still trigger an update to handleToDoUpdate
addToDo() {
firebase.database()
.ref('users/1234/todos')
.set({
...this.todos, {
name: 'Yet another todo...',
complete: false,
},
});
}
// Render a ToDo row
renderToDo(todo) {
// Dont render the todo if its complete
if (todo.complete) {
return null;
}
return (
<View>
<Text>{todo.name}</Text>
</View>
);
}
// Render the list of ToDos with a Button
render() {
return (
<View>
<ListView
dataSource={this.state.todos}
renderRow={(...args) => this.renderToDo(...args)}
/>
<Button
title={'Add ToDo'}
onPress={() => this.addToDo}
/>
<View>
);
}
```
#### Differences between `.on` & `.once`
With persistence enabled, any calls to a ref with `.once` will always read the data from disk and not contact the server.
On behaves differently, by first checking for a connection and if none exists returns the persisted data. If it successfully connects
to the server, the new data will be returned and the disk data will be updated.
The database refs has a `keepSynced()` function to tell the RNFirebase library to keep the data at the `ref` in sync.
```javascript
const ref = firebase.database
.ref('chat-messages')
.child('roomId');
ref.keepSynced(true);
```
#### Security rules and offline persistence
Bear in mind that security rules live on the firebase server and **not in the client**. In other words, when offline, your app knows nothing about your database's security rules. This can lead to unexpected behaviour, which is explained in detail in the following blog post: https://firebase.googleblog.com/2016/11/what-happens-to-database-listeners-when-security-rules-reject-an-update.html
Some examples of behaviour you may not expect but may encounter are:
- Values that should not be readable, according to your security rules, are readable if they were created on the same device.
- Values are readable even when not authenticated, if they were created on the same device.
- Locations are writable even when they should not be, according to your security rules. This is more likely to cause unwanted behaviour when your app is offline, because when it is *online* the SDK will very quickly roll back the write once the server returns a permission error.

View File

@ -1,66 +0,0 @@
# Performance Monitoring
!> Performance monitoring requires react-native-firebase version 1.2.0.
?> Android: If you plan on using this module in your own application, please ensure the optional setup instructions for
[Android](http://invertase.io/react-native-firebase/#/installation-android?id=_4-performance-monitoring-optional) have been followed.
Out of the box, [Firebase Performance Monitoring](https://firebase.google.com/docs/perf-mon/automatic) monitors a number of
[automatic traces](https://firebase.google.com/docs/perf-mon/automatic) such as app start/background/foreground response times.
You can easily trace your own events with RNFirebase:
## API
#### setPerformanceCollectionEnabled(enabled: `boolean`)
Globally enables or disables performance monitoring capture across the app.
```js
firebase.perf().setPerformanceCollectionEnabled(false); // Disable
```
#### newTrace(id: `string`): `Trace`
Returns a new instance of Trace (see API below). The id is the unique name of something you'd like to run performance
monitoring against.
```js
const trace = firebase.perf().newTrace("test_trace");
```
### Trace
!> Once a trace has been started and stopped, you cannot re-start it in the same app lifecycle.
#### start()
Initializes the trace to start tracing performance to relay back to Firebase.
```js
trace.start();
```
#### incrementCounter(event: string)
Notifies Firebase an event has occured. These events will be visible on Firebase once your trace has stopped.
```js
someCacheService.get('user:123')
.then((user) => {
if (user) {
trace.incrementCounter('user_cache_hit');
} else {
trace.incrementCounter('user_cache_missed');
}
});
```
#### stop()
Stops performance tracing. The completed trace stats are now sent to Firebase.
?> Results are not realtime. They can take a number of hours to appear in the Firebase console.
```js
trace.stop();
```

View File

@ -1,100 +0,0 @@
# Storage
RNFirebase mimics the [Web Firebase SDK Storage](https://firebase.google.com/docs/storage/web/start), whilst
providing some iOS and Android specific functionality.
## Uploading files
### Simple
```javascript
firebase.storage()
.ref('/files/1234')
.putFile('/path/to/file/1234')
.then(uploadedFile => {
//success
})
.catch(err => {
//Error
});
```
### With metadata
```javascript
const metadata = {
contentType: 'image/jpeg'
}
firebase.storage()
.ref('/files/1234')
.putFile('/path/to/file/1234', metadata)
```
### Listen to upload state
```javascript
const unsubscribe = firebase.storage()
.ref('/files/1234')
.putFile('/path/to/file/1234')
.on('state_changed', snapshot => {
//Current upload state
}, err => {
//Error
unsubscribe();
}, uploadedFile => {
//Success
unsubscribe();
});
```
## Downloading files
### Simple
```javascript
firebase.storage()
.ref('/files/1234')
.downloadFile('/path/to/save/file')
.then(downloadedFile => {
//success
})
.catch(err => {
//Error
});
```
### Listen to download state
```javascript
const unsubscribe = firebase.storage()
.ref('/files/1234')
.downloadFile('/path/to/save/file')
.on('state_changed', snapshot => {
//Current download state
}, err => {
//Error
unsubscribe();
}, downloadedFile => {
//Success
unsubscribe();
});
```
## TODO
There are a few methods which have not yet been implemented for Storage:
### Reference
- put()
- putString()
### UploadTask
- cancel()
- pause()
- resume()
### DownloadTask
- cancel()
- pause()
- resume()

View File

@ -1,35 +0,0 @@
# Transactions
?> For help on how to use firebase transactions please see the [Firebase Transaction Documentation](https://firebase.google.com/docs/reference/js/firebase.database.Reference#transaction).
### Android Implementation
The [android implementation](https://github.com/invertase/react-native-firebase/blob/master/android/src/main/java/io/invertase/firebase/database/RNFirebaseTransactionHandler.java) makes use of [Condition](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Condition.html) and [ReentrantLock](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantLock.html) locks to handle transactions across the React Native Bridge.
### iOS Implementation
The [iOS implementation](https://github.com/invertase/react-native-firebase/blob/master/ios/RNFirebase/RNFirebaseDatabase.m#L279) makes use of GCD (Grand Central Dispatch) to handle transactions across the React Native Bridge without blocking the application thread. Check out [this](https://mikeash.com/pyblog/friday-qa-2011-10-14-whats-new-in-gcd.html) post for some 'light' reading about it.
!> Transactions that receive no response from react native's JS thread within 30 seconds are automatically aborted - this value is currently not configurable - PR welcome.
## Example
```javascript
const ref = firebase.database().ref('user/posts');
ref.transaction((posts) => {
return (posts || 0) + 1;
}, (error, committed, snapshot) => {
if (error) {
console.log('Something went wrong', error);
} else if (!committed) {
console.log('Aborted'); // Returning undefined will trigger this
} else {
console.log('User posts incremented by 1');
}
console.log('User posts is now: ', snapshot.val());
});
```

View File

@ -1,125 +0,0 @@
# Usage with Redux
Although RNFirebase usage requires a React Native environment, it isn't tightly coupled which allows for full flexibility
when it comes to integrating with other modules such a [`react-redux`](https://github.com/reactjs/react-redux). If you wish to use
a Redux library designed for Firebase, we suggest taking a look at [`react-redux-firebase`](http://docs.react-redux-firebase.com/history/v2.0.0/docs/recipes/react-native.html)
for implementation with this module.
## Standalone integration
Although the following example works for a basic redux setup, it may differ when integrating with other redux middleware.
Imagine a simple TODO app, with redux we're able to abstract the Firebase logic out of components which allows for greater
testability and maintainability.
?> We use [`redux-thunk`](https://github.com/gaearon/redux-thunk) to provide async actions.
### Action Creators
```js
// Actions
export const subscribe = () => {
return (dispatch) => {
firebase.database().ref('todos').on('value', (snapshot) => {
const todos = [];
snapshot.forEach((childSnapshot) => {
todos.push({
id: childSnapshot.key,
...(childSnapshot.val()),
})
})
dispatch({
type: 'TODO_UPDATE',
todos,
})
})
}
}
// Methods
export const addTodo = text => {
firebase.database().ref('todos').push({
text,
visible: true,
})
}
export const completeTodo = id => {
firebase.database().ref(`todos/${id}`).update({
visible: false,
})
}
```
Instead of creating multiple actions which the reducers handle, we instead subscribe to the database ref and on any changes,
send a single action for the reducers to handle with the data which is constantly updating.
### Reducers
Our reducer now becomes really simple, as we're able to simply update the reducers state with whatever data has been returned
from our Firebase subscription.
```js
const todos = (state = {}, action) => {
switch (action.type) {
case 'TODO_UPDATE':
return { ...action.todos };
}
return state;
}
export default todos;
```
### Component
We can now easily subscribe to the todos in redux state and get live updates when Firebase updates.
```js
import React from 'react';
import { FlatList } from 'react-native';
import { connect } from 'react-redux';
import { subscribe, addTodo, completeTodo } from '../actions/TodoActions.js';
...
class Todos extends React.Component {
componentDidMount() {
this.props.dispatch(
subscribe()
);
}
onComplete = (id) => {
this.props.dispatch(
completeTodo(id)
);
};
onAdd = (text) => {
this.props.dispatch(
addTodo(text)
);
};
render() {
return (
<FlatList
data={this.props.todos}
...
/>
);
}
}
function mapStateToProps(state) {
return {
todos: state.todos,
};
}
export default connect(mapStateToProps)(Todos);
```

View File

@ -1,38 +0,0 @@
# Usage
After creating a Firebase project and installing the library, we can use it in our project by importing the library in our JavaScript:
```javascript
import RNFirebase from 'react-native-firebase'
```
We need to tell the Firebase library we want to _configure_ the project. RNFirebase provides a way to configure both the native and the JavaScript side of the project at the same time with a single command:
```javascript
const firebase = RNFirebase.initializeApp({
// config options
});
```
## Configuration Options
| option | type | Default Value | Description |
|----------------|----------|-------------------------|----------------------------------------|
| debug | bool | false | When set to true, RNFirebase will log messages to the console and fire `debug` events we can listen to in `js` |
| persistence | bool | false | When set to true, database persistence will be enabled. |
| errorOnMissingPlayServices | bool | true | (Android only) When set to true, will throw an error if Google Play Services isn't installed. |
| promptOnMissingPlayServices | bool | true | (Android only) When set to true, will prompt the user to install Google Play Services if it isn't installed. This takes precedence over `errorOnMissingPlayServices`.|
For instance:
```javascript
import RNFirebase from 'react-native-firebase';
const configurationOptions = {
debug: true
};
const firebase = RNFirebase.initializeApp(configurationOptions);
export default firebase;
```