Firebase Data Connect client SDKs let you call your server-side queries and mutations directly from a Firebase app. You generate a custom client SDK in parallel as you design the schemas, queries and mutations you deploy to your Data Connect service. Then, you integrate methods from this SDK into your client logic.
As we've mentioned elsewhere, it's important to note that Data Connect queries and mutations are not submitted by client code and executed on the server. Instead, when deployed, Data Connect operations are stored on the server like Cloud Functions. This means you need to deploy corresponding client-side changes to avoid breaking existing users (for example, on older app versions).
That's why Data Connect provides you with a developer environment and tooling that lets you prototype your server-deployed schemas, queries and mutations. It also generates client-side SDKs automatically, while you prototype.
When you've iterated updates to your service and client apps, both server- and client-side updates are ready to deploy.
Implement client code with the Firebase JavaScript SDK
This section covers how you can implement clients using the Firebase JavaScript SDK.
If you're using React, see alternate setup instructions and links to additional documentation about generating React SDKs for Data Connect.
Initialize your app
First, initialize your app using the standard Firebase sequence.
initializeApp({...});
Generate your JavaScript SDK
As with most Firebase projects, work on your Firebase Data Connect client code takes place in a local project directory. Both the Data Connect VS Code extension and the Firebase CLI are important local tools for generating and managing client code.
SDK generation options are keyed to several entries in the dataconnect.yaml
file generated when you initialized your project.
Initialize SDK generation
In yourconnector.yaml
, add your outputDir
, package
and (for the web SDK)
packageJsonDir
.
generate:
javascriptSdk:
outputDir: "../movies-generated"
package: "@movie-app/movies"
packageJsonDir: "../../"
outputDir
specifies where the generated SDK should output to.
package
specifies the package name.
packageJsonDir
specifies where to install the package.
In this case, install firebase@latest
to ensure this peer dependency is fulfilled.
Initialize the JavaScript SDK
Initialize your Data Connect instance using the information you used to set up Data Connect (all available in the Firebase console Data Connect tab).
The ConnectorConfig object
The SDK requires a connector configuration object.
This object is automatically generated from serviceId
and location
in
dataconnect.yaml
, and connectorId
in connector.yaml
.
Import libraries
There are two sets of imports needed to initialize your client code: general Data Connect imports and specific, generated SDK imports.
Note the ConnectorConfig
object included in the general imports.
// general imports
import { ConnectorConfig, DataConnect, getDataConnect, QueryRef, MutationRef, QueryPromise, MutationPromise } from 'firebase/data-connect';
// generated queries and mutations from SDK
import { listMovies, ListMoviesResponse, createMovie, connectorConfig } from '@myorg/myconnector';
Use queries from the JavaScript SDK
The generated code will already come with predefined Query Refs. All you need to do is import and call execute on them.
import { executeQuery } from 'firebase/data-connect';
import { listMoviesRef } from '@movie-app/movies';
const ref = listMoviesRef();
const { data } = await executeQuery(ref);
console.log(data.movies);
Call SDK query methods
Here's an example using these action shortcut functions:
import { listMovies } from '@movie-app/movies';
function onBtnClick() {
// This will call the generated JS from the CLI and then make an HTTP request out // to the server.
listMovies().then(data => showInUI(data)); // == executeQuery(listMoviesRef);
}
Subscribe to changes
You can subscribe to changes (which will update any time you execute a query).
const listRef = listAllMoviesRef();
// subscribe will immediately invoke the query if no execute was called on it previously.
subscribe(listRef, ({ data }) => {
updateUIWithMovies(data.movies);
});
await createMovie({ title: 'Empire Strikes Back', releaseYear: 1980, genre: "Sci-Fi", rating: 5 });\
await listMovies(); // will update the subscription above`
Use mutations from the JavaScript SDK
Mutations are accessible the same way as queries.
import { executeMutation } from 'firebase/data-connect';
import { createMovieRef } from '@movie-app/movies';
const { data } = await executeMutation(createMovieRef({ movie: 'Empire Strikes Back' }));
Connect to the Data Connect emulator
Optionally, you can connect to the emulator by calling
connectDataConnectEmulator
and then passing in the Data Connect
instance, like so:
import { connectDataConnectEmulator } from 'firebase/data-connect';
import { connectorConfig } from '@myorg/myconnector'; // Replace with your package name
const dataConnect = getDataConnect(connectorConfig);
connectDataConnectEmulator(dataConnect, 'localhost', 9399);`
// Make calls from your app
To switch to production resources, comment out lines for connecting to the emulator.
Implement client code for React
Firebase Data Connect provides a generated SDK with hooks for React using a library available from our partners at Invertase, TanStack Query Firebase.
This library provides a set of hooks that greatly ease handling of asynchronous tasks with Firebase in your applications.
Initialize your app
First, as with any Firebase web app, initialize your app using the standard Firebase sequence.
initializeApp({...});
Install TanStack Query Firebase packages
install packages for TanStack Query in your project.
npm i --save @tanstack/react-query @tanstack-query-firebase/react
npm i --save firebase@latest # Note: React has a peer dependency on ^11.3.0
Generate your React SDK
As with the standard web SDK, as described earlier, Firebase tooling handles automatic generation of SDKs based on your schema and operations.
To generate a React SDK for your project, add a react
key to your
connector.yaml
configuration file.
generate:
javascriptSdk:
react: true
outputDir: "../movies-generated"
package: "@movie-app/movies"
packageJsonDir: "../../"
Import libraries
There are four sets of imports needed to initialize your React client code: general Data Connect imports, general TanStack imports, and specific imports for your JS and React generated SDKs.
Note the ConnectorConfig
type included in the general imports.
// general imports
import { ConnectorConfig, DataConnect, getDataConnect, QueryRef, MutationRef, QueryPromise, MutationPromise } from 'firebase/data-connect';
// TanStack Query-related functions
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
// generated queries and mutations from SDK
import { ListMoviesResponse, connectorConfig } from '@myorg/myconnector';
// generated React hooks from SDK
import { useListAllMovies, useCreateMovie } from "@myorg/connector/react";
Use queries and mutations in your React client
With setup complete, you can incorporate methods from the generated React SDK.
In the following snippet, notice the use
-prefixed method useListAllMovies
from the generated React SDK. All such use
operations in the generated SDK,
both queries and mutations, call TanStack Query bindings:
- Queries call and return the TanStack
useDataConnectQuery
hook - Mutations call and return the TanStack
useDataConnectMutation
hook
import { useListAllMovies } from '@movies-app/movies/react';
function MyComponent() {
const { isLoading, data, error } = useListAllMovies();
if(isLoading) {
return <div>Loading...</div>
}
if(error) {
return <div> An Error Occurred: {error} </div>
}
}
// App.tsx
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import MyComponent from './my-component';
function App() {
const queryClient = new QueryClient();
return <QueryClientProvider client={queryClient}>
<MyComponent />
</QueryClientProvider>
}
Connect to the Data Connect emulator
Optionally, you can connect to the emulator by calling
connectDataConnectEmulator
and then passing in the Data Connect
instance to your generated hook, like so:
import { getDataConnect, connectDataConnectEmulator } from 'firebase/data-connect';
import { connectorConfig } from '@movies-app/movies';
import { useListAllMovies } from '@movies-app/movies/react';
const dc = getDataConnect(connectorConfig);
connectDataConnectEmulator(dc, 'localhost', 9399);
function App() {
...
const { isLoading, data, error } = useListAllMovies(dc);
...
}
To switch to production resources, comment out lines for connecting to the emulator.
Data types in the SDK
The Data Connect server represents common GraphQL data types. These are represented in the SDK as follows.
Data Connect Type | TypeScript |
---|---|
Timestamp | string |
Date | string |
UUID | string |
Int64 | string |
Double | Number |
Float | Number |
Special considerations for SDK generation
Configure paths relative to node_modules
For the JavaScript SDK, because Data Connect uses npm link
to
install your SDK, your generated SDK needs to be output to a directory at
the same level as your node_modules
path or in a child directory that can
access node_modules
.
In other words, your generated SDK needs to have access to the firebase
node module to work correctly.
For example, if you have your node_modules
in my-app/
, then your output
directory should be my-app/js-email-generated
so that js-email-generated
can
import from its parent node_modules
folder.
my-app/
dataconnect/
connector/
connector.yaml
node_modules/
firebase/
js-email-generated/
// connector.yaml
connectorId: "my-connector"
generate:
javascriptSdk:
outputDir: "../../js-email-generated"
package: "@myapp/my-connector"
Or, if you have a monorepo where your modules are hosted at the root, you can place your output directory in any folder in your monorepo.
my-monorepo/
dataconnect/
connector/
connector.yaml
node_modules/
firebase/
my-app/
js-email-generated/
package.json
// connector.yaml
connectorId: "my-connector"
generate:
javascriptSdk:
outputDir: "../../my-app/js-email-generated" # You can also output to ../../js-email-generated
Update SDKs while prototyping
If you're prototyping interactively with the Data Connect VS Code extension
and its Data Connect emulator, SDK source files are automatically
generated and updated while you modify .gql
files defining schemas, queries
and mutations. This can be a useful feature in hot (re)loading workflows.
.gql
updates and also have SDK
sources automatically updated.
Alternatively, you can use the CLI to regenerate SDKs whenever .gql files are changed:
firebase dataconnect:sdk:generate --watch
Generate SDKs for integration and for production releases
In some scenarios, such as preparing project sources to submit for CI tests, you can call the Firebase CLI for a batch update.
In these cases, use firebase dataconnect:sdk:generate
.
Other frameworks considerations
Angular
When generating code, the Angular CLI
won't pick up on new changes due to
its dependency optimization code. In order to fix this, you will need to modify
your angular.json
.
"projects": {
"myproject": {
"architect": {
"serve:": {
"prebundle": {
"exclude": ["@movie-app/movies"]
}
}
}
}
}