API Reference

Please note that this reference is under construction. With that said, most things in the API should be available here.

Types, values and functions#

allFieldsMasked#

type allFieldsMasked = {.}

If you see this, it means that all fields have been masked in this selection, which is why it contains no data. Relay uses data masking to hide data you haven't explicitly asked for, even if it exists on the object.

Why am I seeing this?#

In most cases when you see this but expected to see actual data, you've spread one or more fragments into a mutation and forgot to add @raw_response_type to your mutation, like:

mutation SomeMutation($input: SomeMutationInput!) @raw_response_type {
...
}

@raw_response_type (documented here) will make sure that you get access to all the data when making optimistic updates.

featureFlags#

type featureFlags = {
mutable enableVariableConnectionKey: bool,
mutable enablePartialRenderingDefault: bool,
mutable enableRelayContainersSuspense: bool,
mutable enablePrecisTypeRefinement: bool,
}

Relay feature flags. Mutate this record as soon as your application boots to enable/disable features.

Example#

/* Make sure this runs before Relay is setup. */
RescriptRelay.featureFlags.enablePrecisTypeRefinement = true

cacheConfig#

type cacheConfig = {
force: option<bool>,
poll: option<int>,
liveConfigId: option<string>,
transactionId: option<string>,
}

The cache config provided to the network layer. Relay won't do anything in particular with these, it's up to you to use them if you want inside of your NetworkLayer.

fetchPolicy#

type fetchPolicy =
| StoreOnly /* Resolve only from the store */
| StoreOrNetwork /* Resolve from the store if all data is there, otherwise make a network request */
| StoreAndNetwork /* Like StoreOrNetwork, but always make a request regardless of if the data was there initially or not */
| NetworkOnly

fetchPolicy controls how you want Relay to resolve your data.

fetchQueryFetchPolicy#

type fetchQueryFetchPolicy =
| NetworkOnly
| StoreOrNetwork

The fetch policies allowed for fetching a query outside of React's render (as in Query.fetch).

mutationError#

type mutationError = {message: string}

An error from a mutation.

arguments#

type arguments

Abstract type for arguments, used when selecting fields on RecordProxy and friends when interacting with the store imperatively.

uploadables#

type uploadables

Abstract type for uploadables.

Constructing an uploadables#

Use makeUploadables : makeUploadables(aJsDictContainingYourFilesHere) to construct an uploadables , and then pass it to your mutation via the uploadables prop. Then, in your network layer, use unwrapUploadables to get the dict with your files again. You can then iterate through that and add the files to your request for upload.

Please note that you'll need to handle sending the uploadables to your server yourself in the network layer. Here's an example in regular JS that you can adapt to ReScript as you need/want.

any#

type any

Abstract helper type to signify something that could not be generated in a type-safe way.

dataId#

type dataId

The type of the id Relay uses to identify records in its store.

Getting dataId 's#

You can get the dataId of anything by selecting __id in your query/fragment/mutation/subscription, like this:

fragment Avatar_user on User {
__id # This is the data id
firstName
lastName
}

If you have globally unique IDs in your graph, __id will always be the same as the regular id. However, as id is commonly modelled as a string, selecting __id will conveniently give you a dataId directly that you can use to interact with the store.

Converting between string and dataId#

You'll often want to convert between string and dataId . You can do this by using makeDataId (RescriptRelay.makeDataId(yourStringHere) and dataIdToString (RescriptRelay.dataIdToString(yourDataIdHere)).

recordSourceRecords#

type recordSourceRecords

An abstract type representing all records in the store serialized to JSON in a way that you can use to re-hydrate the store.

See RecordSource.toJSON for how to produce it.

dataIdToString#

let dataIdToString: dataId => string

Read more about: dataId

Turns a dataId into a string.

makeArguments#

let makeArguments: {..} => arguments

Read more about: arguments

Construct an arguments object for use with certain Relay store APIs.

Usage#

Use it like this: makeArguments({ "someArgument": someValue, "anotherArgument": anotherValue }). Notice the "" surrounding the property names - these are important and tells ReScript that we want this to be a JS object.

generateClientID#

let generateClientID: (~dataId: dataId, ~storageKey: string, ~index: int=?, unit) => dataId

Read more about: dataId

This generates a dataId for use on the client side. However, this is farily low level, and what you're probably really looking for is generateUniqueClientID that'll let you generate a new, unique dataId that you can use for client side only records (like when doing optimistic updates).

generateUniqueClientID#

let generateUniqueClientID: unit => dataId

Read more about: dataId

This generates a unique dataId that's safe to use on the client side. Useful when doing optimistic updates and you need to create IDs that the optimistic update can use.

isClientID#

let isClientID: dataId => bool

Read more about: dataId

Checks whether the provided dataId is guaranteed to be a client side only id.

relayFeatureFlags#

let relayFeatureFlags: featureFlags

Read more about: featureFlags

Relay feature flags. Mutate this record as soon as your application boots to enable/disable features.

Example#

/* Make sure this runs before Relay is setup. */
RescriptRelay.featureFlags.enablePrecisTypeRefinement = true

storeRootId#

let storeRootId: dataId

Read more about: dataId

An abstract type representing all records in the store serialized to JSON in a way that you can use to re-hydrate the store.

See RecordSource.toJSON for how to produce it.

storeRootType#

let storeRootType: string

The type for the Relay store's root RecordProxy .

makeDataId#

let makeDataId: string => dataId

Read more about: dataId

Turns a string into a dataId .

Example#

module User = %relay(`
fragment SomeModule_user on User {
id
}
`)
@react.component
let make = (~user) => {
let user = Fragment.use(user)
/* This converts `user.id` to a [dataId](#dataid) , letting you use it to interact with the store. */
let idAsDataId = RescriptRelay.makeDataId(user.id)
}

makeUploadables#

let makeUploadables: Js.Dict.t<'file> => uploadables

Read more about: uploadables

Construct an uploadables object that you can use for uploads via Relay.

Usage#

Use it like this: makeUploadables(myJsDictWithMyFiles).

unwrapUploadables#

let unwrapUploadables: uploadables => Js.Dict.t<'file>

Read more about: uploadables

Unwraps an uploadables into a Js.Dict.t, letting you set the file format you expect. You can then loop through that dict to add all the files you want to upload to your request in the network layer.

RecordProxy#

Read the following section on working with the Relay store: https://relay.dev/docs/en/relay-store

RecordProxy.t#

type t

Read the following section on working with the Relay store: https://relay.dev/docs/en/relay-store

RecordProxy.getLinkedRecords#

let getLinkedRecords: (
t,
~name: string,
~arguments: arguments=?,
unit,
) => option<array<option<t>>>

Read more about: RecordProxy.t, arguments

Gets an array of linked records, for when a field is a list (meaning a link to multiple records).

RecordProxy.copyFieldsFrom#

let copyFieldsFrom: (t, ~sourceRecord: t) => unit

Read more about: RecordProxy.t

Read the following section on working with the Relay store: https://relay.dev/docs/en/relay-store

RecordProxy.getDataId#

let getDataId: t => dataId

Read more about: RecordProxy.t, dataId

Gets the dataId for a particular record.

RecordProxy.getLinkedRecord#

let getLinkedRecord: (t, ~name: string, ~arguments: arguments=?, unit) => option<t>

Read more about: RecordProxy.t, arguments

Gets a single linked record. A linked record is another object in the store, and not a scalar field like an int or float.

RecordProxy.getOrCreateLinkedRecord#

let getOrCreateLinkedRecord: (
t,
~name: string,
~typeName: string,
~arguments: arguments=?,
unit,
) => t

Read more about: RecordProxy.t, arguments

Gets an array of linked records, for when a field is a list (meaning a link to multiple records).

RecordProxy.getType#

let getType: t => string

Read more about: RecordProxy.t

Returns the __typename of this particular record.

RecordProxy.getValueString#

let getValueString: (t, ~name: string, ~arguments: arguments=?, unit) => option<string>

Read more about: RecordProxy.t, arguments

Returns a field value, expecting it to be a string.

RecordProxy.getValueStringArray#

let getValueStringArray: (
t,
~name: string,
~arguments: arguments=?,
unit,
) => option<array<option<string>>>

Read more about: RecordProxy.t, arguments

Returns a field value, expecting it to be an array of strings.

RecordProxy.getValueInt#

let getValueInt: (t, ~name: string, ~arguments: arguments=?, unit) => option<int>

Read more about: RecordProxy.t, arguments

Returns a field value, expecting it to be an int.

RecordProxy.getValueIntArray#

let getValueIntArray: (
t,
~name: string,
~arguments: arguments=?,
unit,
) => option<array<option<int>>>

Read more about: RecordProxy.t, arguments

Returns a field value, expecting it to be an array of ints.

RecordProxy.getValueFloat#

let getValueFloat: (t, ~name: string, ~arguments: arguments=?, unit) => option<float>

Read more about: RecordProxy.t, arguments

Returns a field value, expecting it to be a float.

RecordProxy.getValueFloatArray#

let getValueFloatArray: (
t,
~name: string,
~arguments: arguments=?,
unit,
) => option<array<option<float>>>

Read more about: RecordProxy.t, arguments

Returns a field value, expecting it to be an array of floats.

RecordProxy.getValueBool#

let getValueBool: (t, ~name: string, ~arguments: arguments=?, unit) => option<bool>

Read more about: RecordProxy.t, arguments

Returns a field value, expecting it to be a boolean.

RecordProxy.getValueBoolArray#

let getValueBoolArray: (
t,
~name: string,
~arguments: arguments=?,
unit,
) => option<array<option<bool>>>

Read more about: RecordProxy.t, arguments

Returns a field value, expecting it to be an array of booleans.

RecordProxy.setLinkedRecord#

let setLinkedRecord: (t, ~record: t, ~name: string, ~arguments: arguments=?, unit) => t

Read more about: RecordProxy.t, arguments

Sets a RecordProxy.t as the linked record for a particular field.

RecordProxy.setLinkedRecords#

let setLinkedRecords: (
t,
~records: array<option<t>>,
~name: string,
~arguments: arguments=?,
unit,
) => t

Read more about: RecordProxy.t, arguments

Sets an array of RecordProxy.t as the linked records for a particular field.

RecordProxy.setValueString#

let setValueString: (t, ~value: string, ~name: string, ~arguments: arguments=?, unit) => t

Read more about: RecordProxy.t, arguments

Sets a string as field value.

RecordProxy.setValueStringArray#

let setValueStringArray: (
t,
~value: array<string>,
~name: string,
~arguments: arguments=?,
unit,
) => t

Read more about: RecordProxy.t, arguments

Sets an array of strings as field value.

RecordProxy.setValueInt#

let setValueInt: (t, ~value: int, ~name: string, ~arguments: arguments=?, unit) => t

Read more about: RecordProxy.t, arguments

Sets an int as field value.

RecordProxy.setValueIntArray#

let setValueIntArray: (
t,
~value: array<int>,
~name: string,
~arguments: arguments=?,
unit,
) => t

Read more about: RecordProxy.t, arguments

Sets an array of ints as field value.

RecordProxy.setValueFloat#

let setValueFloat: (t, ~value: float, ~name: string, ~arguments: arguments=?, unit) => t

Read more about: RecordProxy.t, arguments

Sets a float as field value.

RecordProxy.setValueFloatArray#

let setValueFloatArray: (
t,
~value: array<float>,
~name: string,
~arguments: arguments=?,
unit,
) => t

Read more about: RecordProxy.t, arguments

Sets an array of floats as field value.

RecordProxy.setValueBool#

let setValueBool: (t, ~value: bool, ~name: string, ~arguments: arguments=?, unit) => t

Read more about: RecordProxy.t, arguments

Sets a boolean as field value.

RecordProxy.setValueBoolArray#

let setValueBoolArray: (
t,
~value: array<bool>,
~name: string,
~arguments: arguments=?,
unit,
) => t

Read more about: RecordProxy.t, arguments

Sets an array of booleans as field value.

RecordProxy.setValueToUndefined#

let setValueToUndefined: (
t,
~name: string,
~arguments: arguments=?,
unit,
) => t

Read more about: RecordProxy.t, arguments

Sets the field value to undefined (meaning Relay will treat it as missing data).

RecordProxy.setValueToNull#

let setValueToNull: (
t,
~name: string,
~arguments: arguments=?,
unit,
) => t

Read more about: RecordProxy.t, arguments

Sets the field value to null.

RecordProxy.setLinkedRecordToUndefined#

let setLinkedRecordToUndefined: (
t,
~name: string,
~arguments: arguments=?,
unit,
) => t

Read more about: RecordProxy.t, arguments

Sets this linked record to undefined (meaning Relay will treat it as missing data).

RecordProxy.setLinkedRecordToNull#

let setLinkedRecordToNull: (
t,
~name: string,
~arguments: arguments=?,
unit,
) => t

Read more about: RecordProxy.t, arguments

Sets this linked record to null.

RecordProxy.setLinkedRecordsToUndefined#

let setLinkedRecordsToUndefined: (
t,
~name: string,
~arguments: arguments=?,
unit,
) => t

Read more about: RecordProxy.t, arguments

Sets the field holding these linked records to undefined (meaning Relay will treat it as missing data).

RecordProxy.setLinkedRecordsToNull#

let setLinkedRecordsToNull: (
t,
~name: string,
~arguments: arguments=?,
unit,
) => t

Read more about: RecordProxy.t, arguments

Sets the field holding these linked records to null.

RecordProxy.invalidateRecord#

let invalidateRecord: t => unit

Read more about: RecordProxy.t

Invalidates this record.

Invalidating a record means that the next time Relay evaluates this record, it'll be treated as missing.

Beware that this doesn't mean that queries using this record will refetch immediately. Rather, it'll happen the next time the query renders. Have a look at useSubscribeToInvalidationState, that'll allow you to subscribe to whenever records are invalidated, if you're looking for a way to refetch immediately as something invalidates.

RecordSourceSelectorProxy#

RecordSourceSelectorProxy and RecordSourceProxy are the two modules representing the store, with various capabilities.

RecordSourceSelectorProxy.t#

type t

Type type representing a RecordSourceSelectorProxy .

RecordSourceSelectorProxy.getPluralRootField#

let getPluralRootField: (t, ~fieldName: string) => option<array<option<RecordProxy.t>>>

Read more about: RecordSourceSelectorProxy.t

Plural version of RecordSourceSelectorProxy.getRootField .

RecordSourceSelectorProxy.create#

let create: (t, ~dataId: dataId, ~typeName: string) => RecordProxy.t

Read more about: RecordSourceSelectorProxy.t, dataId, RecordProxy, RecordProxy.t

Type type representing a RecordSourceSelectorProxy .

RecordSourceSelectorProxy.delete#

let delete: (t, ~dataId: dataId) => unit

Read more about: RecordSourceSelectorProxy.t, dataId

Deletes the RecordProxy with the provided dataId .

RecordSourceSelectorProxy.get#

let get: (t, ~dataId: dataId) => option<RecordProxy.t>

Read more about: RecordSourceSelectorProxy.t, dataId

Returns the RecordProxy with the provided dataId , if it exists.

RecordSourceSelectorProxy.getRoot#

let getRoot: t => RecordProxy.t

Read more about: RecordSourceSelectorProxy.t, RecordProxy, RecordProxy.t

Returns the root RecordProxy , meaning the RecordProxy holding your top level fields.

RecordSourceSelectorProxy.getRootField#

let getRootField: (t, ~fieldName: string) => option<RecordProxy.t>

Read more about: RecordSourceSelectorProxy.t

Returns the RecordProxy for the fieldName at root. You should prefer using RecordSourceSelectorProxy.getRoot() and traverse from there if you need access to root fields rather than use this.

RecordSourceSelectorProxy.invalidateStore#

let invalidateStore: t => unit

Read more about: RecordSourceSelectorProxy.t

Plural version of RecordSourceSelectorProxy.getRootField .

ConnectionHandler#

Read the Relay docs section on ConnectionHandler

ConnectionHandler.getConnection#

let getConnection: (
~record: RecordProxy.t,
~key: string,
~filters: arguments=?,
unit,
) => option<RecordProxy.t>

Read more about: arguments, RecordProxy, RecordProxy.t

For a RecordProxy , returns the RecordProxy that is at the connection config provided.

ConnectionHandler.createEdge#

let createEdge: (
~store: RecordSourceSelectorProxy.t,
~connection: RecordProxy.t,
~node: RecordProxy.t,
~edgeType: string,
) => RecordProxy.t

Read more about: RecordProxy, RecordProxy.t, RecordSourceSelectorProxy, RecordSourceSelectorProxy.t, RecordSource

Creates an edge for a particular connection.

ConnectionHandler.insertEdgeBefore#

let insertEdgeBefore: (
~connection: RecordProxy.t,
~newEdge: RecordProxy.t,
~cursor: string=?,
unit,
) => unit

Read more about: RecordProxy, RecordProxy.t

Inserts an edge into a connection before the provided cursor. If no cursor is provided, it inserts the edge at the start of the connection list.

ConnectionHandler.insertEdgeAfter#

let insertEdgeAfter: (
~connection: RecordProxy.t,
~newEdge: RecordProxy.t,
~cursor: string=?,
unit,
) => unit

Read more about: RecordProxy, RecordProxy.t

Inserts an edge into a connection after the provided cursor. If no cursor is provided, it inserts the edge at the end of the connection list.

ConnectionHandler.deleteNode#

let deleteNode: (~connection: RecordProxy.t, ~nodeId: dataId) => unit

Read more about: dataId, RecordProxy, RecordProxy.t

Deletes any edge from the connection where the node of the edge has the provided dataId . Please not that this will not remove the actual node from the store. Use RecordSourceSelectorProxy.delete for that.

Observable#

A Relay observable, used throughout Relay for delivering data, in particular when dealing with multiple payloads like with subscriptions or multipart responses like @stream or @defer.

Observable.subscription#

type subscription = {
unsubscribe: unit => unit,
closed: bool,
}

A subscription for an observable, allowing you to unsubscribe if wanted.

Observable.makeObserver#

let makeObserver: (
~start: subscription => unit=?,
~next: 'response => unit=?,
~error: Js.Exn.t => unit=?,
~complete: unit => unit=?,
~unsubscribe: subscription => unit=?,
unit,
) => observer<'response>

Read more about: Observable.subscription

The type representing the observable.

Observable.make#

let make: (sink<'t> => option<subscription>) => t<'t>

Create a new observable, getting fed an Observable.sink for interacting with the observable, and optionally returning a Observable.subscription if you have things you want to unsubscribe from as the observable closes.

Observable.subscribe#

let subscribe: (t<'t>, observer<'t>) => subscription

Read more about: Observable.subscription

Subscribe to the Observable.t using an observer.

Observable.toPromise#

let toPromise: t<'t> => Promise.t<'t>

Turns an Observable into a promise. Beware that reading the response in the resulting promise is currently not safe due to some internals of how ReScript Relay works. This will be resolved in the future.

Network#

Represents the network layer.

Network.operation#

type operation = {
id: string,
text: string,
name: string,
operationKind: string,
}

The operation fed to the NetworkLayer when Relay wants to make a request. Please note that if you're using persisted queries, id will exist but text won't, and vice versa when not using persisted queries.

Network.subscribeFn#

type subscribeFn = (operation, Js.Json.t, cacheConfig) => Observable.t<Js.Json.t>

Read more about: Observable

The shape of the function Relay expects for creating a subscription.

Network.fetchFunctionPromise#

type fetchFunctionPromise = (
operation,
Js.Json.t,
cacheConfig,
Js.Nullable.t<uploadables>,
) => Js.Promise.t<Js.Json.t>

The shape of the function responsible for fetching data if you want to return a promise rather than an Observable .

Network.fetchFunctionObservable#

type fetchFunctionObservable = (
operation,
Js.Json.t,
cacheConfig,
Js.Nullable.t<uploadables>,
) => Observable.t<Js.Json.t>

Read more about: Observable

The shape of the function responsible for fetching data if you want to return an Observable .

Network.t#

type t

The type representing an instantiated NetworkLayer.

Network.makePromiseBased#

let makePromiseBased: (
~fetchFunction: fetchFunctionPromise,
~subscriptionFunction: subscribeFn=?,
unit,
) => t

Read more about: Network.subscribeFn, Network.fetchFunctionPromise, Network.t

The type representing an instantiated NetworkLayer.

Network.makeObservableBased#

let makeObservableBased: (
~observableFunction: fetchFunctionObservable,
~subscriptionFunction: subscribeFn=?,
unit,
) => t

Read more about: Network.subscribeFn, Network.fetchFunctionObservable, Network.t

Create a new NetworkLayer using a fetch function that returns an Observable .

RecordSource#

RecordSource is the source of records used by the store. Can be initiated with or without prior records; eg. hydrating the store with prior data.

RecordSource.t#

type t

The type representing an instantiated RecordSource .

RecordSource.make#

let make: (~records: recordSourceRecords=?, unit) => t

Read more about: recordSourceRecords, RecordSource.t

The type representing an instantiated RecordSource .

RecordSource.toJSON#

let toJSON: t => recordSourceRecords

Read more about: RecordSource.t, recordSourceRecords

Serializes the RecordSource into recordSourceRecords that you can use to rehydrate another store. Typically used for SSR.

Store#

The actual store module, with configuration for the store.

Store.t#

type t

The type representing an instantiated Store .

Store.make#

let make: (
~source: RecordSource.t,
~gcReleaseBufferSize: /* `gcReleaseBufferSize` controls how many queries are allowed to be cached by default. Increase this to increase the size of the cache. */
int=?,
~queryCacheExpirationTime: int /* `queryCacheExpirationTime` sets a TTL (time to live) for all queries. If that time passes, the data is considered stale and is evicted from the store. Default is no TTL. */=?,
unit,
) => t

Read more about: RecordSource, RecordSource.t, Store.t

Creates a new Store .

Store.getSource#

let getSource: t => RecordSource.t

Read more about: Store.t, RecordSource, RecordSource.t

The type representing an instantiated Store .

Store.publish#

let publish: (t, RecordSource.t) => unit

Read more about: Store.t

Publishes new records to this store. This is useful in particular with frameworks like Next.js where routes could preload data needed and then serialize that (using RecordSource.toJSON ) and send it over the wire, but you already have a store instantiated client side. This will then allow you to publish those records into your existing store.

Pseudo-example#

/* A Next.js route component */
@react.component
let make = (~serializedRecords: RescriptRelay.recordSourceRecords) => {
let environment = RescriptRelay.useEnvironmentFromContext()
/* Make sure we only run this once */
React.useEffect2(() => {
/* This will publish the records to the existing store */
environment->RescriptRelay.Store.publish(serializedRecords)
None
}, (environment, serializedRecords))
}

Environment#

Module representing the environment, which you'll need to use and pass to various functions. Takes a few configuration options like store and network layer.

Environment.t#

type t

The type representing an instantiated Environment .

Environment.make#

let make: (
~network: Network.t,
~store: Store.t,
~getDataID: (
~nodeObj: {.."__typename": string, "id": string} as 'a,
~typeName: string,
) => string=?,
~treatMissingFieldsAsNull: bool=?,
unit,
) => t

Read more about: Network, Network.t, Store, Store.t, Environment.t

Create a new Environment .

Environment.getStore#

let getStore: t => Store.t

Read more about: Environment.t, Store, Store.t

The type representing an instantiated Environment .

Environment.commitPayload#

let commitPayload: (t, operationDescriptor, 'payload) => unit

Read more about: Environment.t

Given an operationDescriptor, commits the corresponding payload.

Disposable#

A disposable is something you can use to dispose of something when you don't use/need it anymore.

Disposable.t#

type t

The type representing a Disposable .

Disposable.dispose#

let dispose: t => unit

Read more about: Disposable.t

The type representing a Disposable .

Context#

Context provider for the Relay environment.

Context.contextShape#

type contextShape = {"environment": Environment.t}

Read more about: Environment, Environment.t

The expected shape of the context.

Context.t#

type t

Type representing the context.

Context.context#

let context: React.Context.t<option<contextShape>>

Type representing the context.

Provider#

The context provider you wrap your app in and pass your Environment for Relay to work.