babangsund

RELAY ENVIRONMENT METHODS

August 18, 20194 minute read

The Relay Environment exposes a set of methods, which you might find useful, should you ever find yourself contributing to Relay - or just building cool new stuff on your own.


check

environment.check is used by Relay to determine whether or not a given set of records are present in the store, which are required to fulfill the provided selector (essentially a normalized query response data signature).

Input signature:

type NormalizationSelector = {|
  +dataID: DataID,
  +node: NormalizationSelectableNode,
  +variables: Variables,
|};

environment.check returns true if all required records are present, otherwise false.

Example usage:

import {getRequest, createOperationDescriptor} from 'relay-runtime';

const request = getRequest(query);
const operation = createOperationDescriptor(request, variables);

const canFulfillRequest = environment.check(operation.root);

retain

environment.retain is handy if you ever need to tell the Relay garbage collection, to retain some data in a garbage collection cycle.

Input signature:

type NormalizationSelector = {|
  +dataID: DataID,
  +node: NormalizationSelectableNode,
  +variables: Variables,
|};

dataID is the relay id of the record you want to retain.
environment.retain returns a disposable, which can be called to discard the record from the list of retained nodes, and schedule a garbage collection cycle.

Example usage:

// with a query
import {getRequest, createOperationDescriptor} from 'relay-runtime';

const request = getRequest(query);
const operation = createOperationDescriptor(request, variables);
const retainDisposable = environment.retain(operation.root);  
// without a query
const retainDisposable = environment.retain({  dataID,
  variables: {},
  node: { selections: [] }
});

// cleanup
retainDisposable();

lookup

environment.lookup returns a snapshot of the most recent data for a given operation. It is used internally by Relay, as can be seen in the QueryRenderer render prop, where the response data snapshot is passed as props.

Input signature:

type SingularReaderSelector = {|
  +kind: 'SingularReaderSelector',
  +dataID: DataID,
  +node: ReaderFragment,
  +owner: RequestDescriptor,
  +variables: Variables,
|};

Example usage:

import {getRequest, createOperationDescriptor} from 'relay-runtime';

const request = getRequest(query);
const operation = createOperationDescriptor(request, variables);

const response = environment.lookup(operation.fragment, operation);// => response.data

response.data is of type SelectorData, which boils down to {[key: string]: mixed}, which is essentially just an object of unknown shape.

subscribe

environment.subscribe subscribes to a provided Snapshot, like the one returned by environment.lookup.
The second argument is a callback, which is triggered by the Relay Store whenever there's an update to the snapshot provided in the first argument.

Upon an update, a new Snapshot is passed, which could then be used to, say, update a QueryRenderer.

Input signature:

snapshot: Snapshot,
callback: (snapshot: Snapshot) => void,

environment.subscribe returns a disposable, which should be called whenever the subscription calls your callback function.

Example usage:

import {getRequest, createOperationDescriptor} from 'relay-runtime';

const request = getRequest(query);
const operation = createOperationDescriptor(request, variables);
const response = environment.lookup(operation.fragment, operation);

const subscribeDisposable = environment.subscribe(response, newSnapshot => {  // do something with newSnapshot
  console.log(newSnapshot.data);
});

// cleanup
subscribeDisposable();

applyUpdate

environment.applyUpdate as the name implies, applies or commits an update to the Relay Store, very much like commitLocalUpdate, except this update will remain rebased on top of the queue until removed.

Input signature:

type OptimisticUpdateFunction = {|
  +storeUpdater: (store: RecordSourceProxy) => void,
|};

environment.applyUpdate returns a disposable, allowing you to revert and dispose any changes made by the storeUpdater function.

The update is re-applied on each request, so make sure to dispose when it is no longer current.

Example usage:

function storeUpdater(store) {
  // do something with store
}
const updaterDisposable = environment.applyUpdate({storeUpdater});
// revert
updaterDisposable();

revertUpdate

environment.revertUpdate very intuitively, reverts an optimistic update.

Input signature:

type OptimisticUpdateFunction = {|
  +storeUpdater: (store: RecordSourceProxy) => void,
|};

Example usage:

function storeUpdater(store) {
  // do something with store
}

// apply
environment.applyUpdate({storeUpdater});

// revert
environment.revertUpdate(storeUpdater);