### Project Setup and Development Commands
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/tutorial/1-intro.md
Commands to clone the example project, install dependencies, and start the development server. This sets up the necessary environment for the tutorial.
```bash
git clone https://github.com/zth/relay-examples.git
cd relay-examples/newsfeed
yarn
yarn dev
```
--------------------------------
### Setup Relay Environment in ReScript
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/getting-started.md
Create a RelayEnv.res file to establish the Relay environment, including a network layer for dispatching GraphQL queries and a store for data caching. It leverages @glennsl/rescript-fetch for HTTP requests to a local GraphQL server. Inputs are GraphQL operation text and variables; outputs are JSON responses. Limitations include hardcoded localhost URL and lack of error handling beyond status checks.
```rescript
/* This is a Rescript's standard library, typically opened globally in rescript.json */
open RescriptCore
/**
* A standard fetch that sends our operation and variables to the
* GraphQL server, and then decodes and returns the response.
*/
let fetchQuery: RescriptRelay.Network.fetchFunctionPromise = async (
operation,
variables,
_cacheConfig,
_uploadables,
) => {
open Fetch
let resp = await fetch(
"http://localhost:4000/graphql",
{
method: #POST,
body: {
"query": operation.text->Nullable.getOr(""),
"variables": variables
}
->JSON.stringifyAny
->Option.getExn
->Body.string,
headers: Headers.fromObject({
"content-type": "application/json",
"accept": "application/json",
}),
},
)
if Response.ok(resp) {
await Response.json(resp)
} else {
panic("Request failed: " ++ Response.statusText(resp))
}
}
let network = RescriptRelay.Network.makePromiseBased(~fetchFunction=fetchQuery)
let environment = RescriptRelay.Environment.make(
~network,
~store=RescriptRelay.Store.make(
~source=RescriptRelay.RecordSource.make(),
~gcReleaseBufferSize=10 /* This sets the query cache size to 10 */
)
)
```
--------------------------------
### Makefile Quick Start Commands for ReScript Relay PPX
Source: https://github.com/zth/rescript-relay/blob/master/packages/rescript-relay/rescript-relay-ppx/README.md
Provides essential Makefile commands for setting up, building, and checking the ReScript Relay PPX project. These commands automate dependency installation and binary compilation.
```bash
make dev-setup
make build
make check
make help
```
--------------------------------
### Install RescriptRelay and React Dependencies (Bash)
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/getting-started.md
Installs React 18 and the necessary RescriptRelay and Relay runtime packages using yarn. It specifies exact versions for Relay runtime and React Relay to ensure compatibility.
```bash
# Add React 18
yarn add react@18 react-dom@18
# Add rescript-relay and dependencies to the project
# We currently depend on Relay version 20.1.1, so install that exact version
yarn add rescript-relay relay-runtime@20.1.1 react-relay@20.1.1
```
--------------------------------
### Add Relay Scripts to package.json
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/getting-started.md
Update package.json to include scripts for running the RescriptRelay compiler once or in watch mode using rescript-relay-compiler. This differs from the standard relay-compiler by adding a custom layer. Dependencies require yarn or npm and the installed rescript-relay-compiler package.
```json
...
"scripts": {
"relay": "rescript-relay-compiler",
"relay:watch": "rescript-relay-compiler --watch"
}
```
--------------------------------
### Configure RescriptRelay ppx-flags and bs-dependencies (JSON)
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/getting-started.md
Configures the ReScript compiler by specifying the 'rescript-relay/ppx' flag and adding 'rescript-relay' and '@rescript/react' to the 'bs-dependencies'. The 'ppx-flags' entry differs for MacOS/Linux vs. Windows.
```json
{
...
"ppx-flags": ["rescript-relay/ppx"],
"bs-dependencies": ["@rescript/react", "rescript-relay"],
...
```
```json
{
...
"ppx-flags": ["rescript-relay/ppx.exe"],
"bs-dependencies": ["@rescript/react", "rescript-relay"],
...
```
--------------------------------
### RescriptRelay Environment Setup (Rescript)
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/relay-resolvers.md
Demonstrates how to set up the RescriptRelay environment with a live store, which is required for Relay resolvers.
```Rescript
RescriptRelay.relayFeatureFlags.enableRelayResolvers = true // If on a version lower than 3.1.0
let environment = RescriptRelay.Environment.make(
~network,
~store=RescriptRelay.Store.make(
~store=RescriptRelay.Store.makeLiveStore(
~source=RescriptRelay.RecordSource.make(),
~gcReleaseBufferSize=10
)
)
)
```
--------------------------------
### Integrate Relay Environment with React Context in ReScript
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/getting-started.md
Wrap the React application in RescriptRelay.Context.Provider to provide the Relay environment via React context. This allows child components to access GraphQL data seamlessly. It requires the environment created in RelayEnv.res to be imported. Outputs enable query execution in components; limitations are none specific beyond standard React context restrictions.
```rescript
ReactDOMExperimental.renderConcurrentRootAtElementWithId(
,
"app",
)
```
--------------------------------
### RescriptRelay Resolver Example (Rescript) - Live Data
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/relay-resolvers.md
Demonstrates using `@live` to expose external data that might update.
```Rescript
/**
* @RelayResolver LocalUser.hasBeenOnlineToday: Boolean
* @live
*/
let hasBeenOnlineToday = user => {
read: _suspenseSentinel => {
UserService.getUserStatus(user.id)
},
subscribe: cb => {
let id = UserService.subscribe(cb)
() => UserService.unsubscribe(id)
},
}
```
--------------------------------
### Publishing Records to Store - ReScript Next.js Example
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/api-reference.md
Demonstrates how to publish pre-serialized records to an existing store in a Next.js application. This pattern is useful for server-side rendering where you need to hydrate the client-side store with data that was pre-loaded on the server. The example shows proper usage of the publish method with React components.
```rescript
/* A Next.js route component */
@react.component
let make = (~serializedRecords: RescriptRelay.recordSourceRecords) => {
let environment = RescriptRelay.useEnvironmentFromContext()
/* Make sure we only run this once */
React.useEffect(() => {
/* This will publish the records to the existing store */
environment->RescriptRelay.Store.publish(serializedRecords)
None
}, (environment, serializedRecords))
}
```
--------------------------------
### Configure Relay Config in JavaScript
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/getting-started.md
Create a relay.config.js file at the project root to define paths for source code, GraphQL schema, artifact directory, and custom scalar types for RescriptRelay. It supports options like autoExhaustiveMutations for handling unions. Dependencies include a GraphQL schema file exported from your API. Note that RescriptRelay mandates specifying an artifactDirectory.
```js
module.exports = {
src: "./src", // Path to the folder containing your ReScript files
schema: "./schema.graphql", // Path to the schema.graphql you've exported from your API. Don't know what this is? It's a saved introspection of what your schema looks like. You can run `npx get-graphql-schema http://path/to/my/graphql/server > schema.graphql` in your root to generate it
artifactDirectory: "./src/__generated__", // The directory where all generated files will be emitted
// Enable this if you want mutations that return unions to always force selecting all union members. Read more in the docs on unions.
autoExhaustiveMutations: true,
// You can add type definitions for custom scalars here.
// Whenever a custom scalar is encountered, the type emitted will correspond to the definition defined here. You can then deal with the type as needed when accessing the data.
customScalarTypes: {
Datetime: "string",
Color: "Color.t",
},
};
```
--------------------------------
### RescriptRelay Resolver Example (Rescript) - Local Model
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/relay-resolvers.md
An example of defining a local model and exposing its fields with resolvers.
```Rescript
// RelayLocalUserModel.res
type t = {
id: string,
name: string,
}
module UserService = {
let getById = id => Some({id, name: "Test User"})
}
/**
* @RelayResolver LocalUser
*/
let localUser = id => {
UserService.getById(id->RescriptRelay.dataIdToString)
}
```
```Rescript
/**
* @RelayResolver LocalUser.name: String
*/
let name = user => {
user.name
}
```
```Rescript
/**
* @RelayResolver LocalUser.nameRepeated(times: Int!): String
*/
let nameRepeated = (user, args) => {
user.name->Js.String2.repeat(args.times)
}
```
--------------------------------
### Manual Build with opam and dune for ReScript Relay PPX
Source: https://github.com/zth/rescript-relay/blob/master/packages/rescript-relay/rescript-relay-ppx/README.md
Demonstrates manual steps to install dependencies and build the ReScript Relay PPX executable using opam and dune. It includes commands for both standard and release builds.
```bash
# Install dependencies
opam install . --deps-only
# Build the PPX (produces _build/default/bin/RescriptRelayPpxApp.exe)
opam exec -- dune build bin/RescriptRelayPpxApp.exe
# Build for release (with static linking on Linux)
opam exec -- dune build --profile release-static bin/RescriptRelayPpxApp.exe
```
--------------------------------
### RescriptRelay Resolver Example (Rescript) - Fragment and Args
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/relay-resolvers.md
Demonstrates a resolver that uses a fragment and arguments to calculate a full name and slice it to a specified length.
```Rescript
module Fragment = %relay(`
fragment UserResolverFullname on User {
firstName
lastName
}
`)
/**
* @RelayResolver User.fullName(maxLength: Int!): String
* @rootFragment UserResolverFullname
*
* A users full name.
*/
let fullName = (user, args) => {
let user = Fragment.readResolverFragment(user)
`${user.firstName} ${user.lastName}`->String.slice(~start=0, ~end=args.maxLength)
}
```
--------------------------------
### Define Newsfeed Fragment with Relay
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/tutorial/9-connections-pagination.md
Defines a Relay fragment for the newsfeed content, specifying the viewer type and connection key for the newsfeed stories. This is the initial setup before enabling pagination.
```rescript
module Fragment = %relay(`
fragment NewsfeedContent_viewer on Viewer {
newsfeedStories(first: 3)
@connection(key: "NewsfeedContentsFragment_newsfeedStories") {
edges {
node {
id
...Story_story
}
}
}
}
`)
```
--------------------------------
### RescriptRelay Resolver Example (Rescript) - Simple Resolver
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/relay-resolvers.md
An example of a simple resolver function in RescriptRelay that checks an online status and returns a boolean.
```Rescript
/**
* @RelayResolver UserMeta.online: Boolean
*/
let online = userMeta => {
if userMeta.online {
true
} else {
panic("Could not lookup online status")
}
}
```
--------------------------------
### Get Store from Environment - Rescript
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/api-reference.md
Retrieves the Store instance from an instantiated Environment. This is useful for interacting directly with the Relay store.
```rescript
let getStore: t => Store.t
```
--------------------------------
### GraphQL Fragment for Friend Edges with Properties
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/tutorial/9-connections-pagination.md
An example GraphQL fragment demonstrating how to query friend connections where edges themselves have properties, such as 'since'. This illustrates the concept of modeling edge data with dedicated nodes.
```graphql
fragment FriendsFragment1 on Viewer {
friends {
since // a property of the edge
node {
name // a property of the friend itself
}
}
}
```
--------------------------------
### RescriptRelay Updatable Query for Local Cache Updates
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/blog/2024-08-06-rescript-relay-3.0.0-released.md
Provides an example of an updatable query in RescriptRelay. This pattern enables type-safe local updates to the Relay cache after mutations or for managing local state.
```rescript
// ViewerCurrentActiveUpdater.res
module Query = %relay(`
query ViewerCurrentlyActiveUpdaterQuery @updatable {
loggedInUser {
currentlyActive
}
}
`)
let updateCurrentlyActive = (currentlyActive: bool, ~environment: RescriptRelay.Environment.t) => {
RescriptRelay.commitLocalUpdate(~environment, ~updater=store => {
let {updatableData} = Query.readUpdatableQuery(store)
updatableData.loggedInUser.currentlyActive = currentlyActive
})
}
```
--------------------------------
### Observable.makeObserver Function
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/api-reference.md
Creates an observer for ReScript Relay Observables. It accepts optional callbacks for start, next, error, complete, and unsubscribe events, allowing fine-grained control over observable interactions.
```rescript
let makeObserver: (
~start: subscription => unit=?,
~next: 'response => unit=?,
~error: Js.Exn.t => unit=?,
~complete: unit => unit=?,
~unsubscribe: subscription => unit=?
) => observer<'response>
```
--------------------------------
### Rescript Relay: Setup for Prefetchable Pagination
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/pagination.md
This snippet shows how to configure a Rescript Relay fragment to enable prefetchable pagination. It requires the `@connection` directive to include `prefetchable_pagination: true`, along with defining arguments for count and cursor.
```rescript
module Fragment = %relay(
`
fragment UserFriends_user on User
@refetchable(queryName: "UserFriendsRefetchQuery")
@argumentDefinitions(
count: {type: "Int!", defaultValue: 10},
cursor: {type: "String!", defaultValue: ""}
) {
friendsConnection(first: $count, after: $cursor)
@connection(key: "UserFriends_friendsConnection", prefetchable_pagination: true)
{
edges {
node {
id
name
...SingleFriend_friend
}
}
}
}
`
)
```
--------------------------------
### Define Relay Query Component with Preloading in ReScript
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/making-queries.md
Defines a Relay query using the %relay decorator with a userId parameter. The component receives a queryRef prop and uses Query.usePreloaded to access the preloaded data. Requires rescript-relay and a router setup to provide the queryRef.
```rescript
/* SomeComponent.res */
module Query = %relay(`
query SomeComponentQuery($userId: ID!) {
user(id: $userId) {
...SomeUserComponent_user
}
}
`)
@react.component
let make = (~queryRef) => {
let queryData = Query.usePreloaded(~queryRef)
/* Use the data for the query here */
}
```
--------------------------------
### Setup network layer for @codesplit directive
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/codesplit-directive.md
Configures the network layer to preload resources for codesplit components. This function should be called after receiving server responses. It takes the operation, variables, and response JSON as parameters to determine which codesplit components to preload.
```rescript
let fetchQuery: RescriptRelay.Network.fetchFunctionPromise = async (
operation,
variables,
_cacheConfig,
_uploadables,
) => {
open Fetch
let resp = await fetch(
"https://your.server/graphql",
{
method: #POST,
body: {
"query": operation.text->Nullable.getOr(""),
"id": operation.id->Nullable.getOr(""),
"variables": variables
}
->JSON.stringifyAny
->Option.getExn
->Body.string,
headers: Headers.fromObject({
"content-type": "application/json",
"accept": "application/json",
}),
},
)
if Response.ok(resp) {
let response = await Response.json(resp)
// change-line
RescriptRelay.Network.preloadResources(~operation, ~variables, ~response)
response
} else {
panic("Request failed: " ++ Response.statusText(resp))
}
}
```
--------------------------------
### Use @preloadable directive for query optimization
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/making-queries.md
Demonstrates how to add the @preloadable directive to GraphQL queries to improve performance. The directive enables preloading of query data, reducing suspense delays when components render. Requires Relay environment setup and Relay Compiler configuration. The example shows a React component using the query with preloadable optimization.
```ReScript
/* SomeComponent.res */
module Query = %relay(`
// color2
query SomeComponentQuery($userId: ID!) {
// change-line
query SomeComponentQuery($userId: ID!) @preloadable {
user(id: $userId) {
...SomeUserComponent_user
}
}
`)
@react.component
let make = (~queryRef) => {
let queryData = Query.usePreloaded(~queryRef)
/* Use the data for the query here */
}
```
--------------------------------
### Compare Nominal and Structural Types in TypeScript
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/tutorial/3-query-basics.md
Illustrates structural typing concepts using TypeScript type definitions and function signatures. Shows how compatible structures can be used interchangeably in structurally typed systems.
```typescript
type A = { name: string };
type B = { name: string };
type C = A & { age: number };
const acceptsA = (arg: A) => {
console.log(arg.name);
};
const valA: A = { name: "Jean Valjean" };
```
--------------------------------
### Demonstrate nominal vs structural typing in ReScript and TypeScript
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/tutorial/3-query-basics.md
Compares type compatibility behaviors between TypeScript's structural typing and ReScript's nominal typing. Shows how TypeScript allows implicit subtyping while ReScript requires explicit coercions. Illustrates type definitions and function calls in both languages.
```typescript
const valB: B = { name: "Jean Valjean" };
const valC: C = { name: "Jean Valjean", age: 64 };
acceptsA(valA);
acceptsA(valB);
acceptsA(valC);
```
```rescript
type a = {name: string}
type b = {name: string}
type c = {...a, age: int}
let acceptsA = (arg: a) => {
Console.log(arg.name)
}
let valA: a = {name: "Jean Valjean"}
let valB: b = {name: "Jean Valjean"}
let valC: c = {name: "Jean Valjean", age: 64}
acceptsA(valA)
acceptsA(valB)
acceptsA(valC)
```
--------------------------------
### Development Workflow Commands for ReScript Relay PPX
Source: https://github.com/zth/rescript-relay/blob/master/packages/rescript-relay/rescript-relay-ppx/README.md
Outlines common commands for a rapid development cycle with the ReScript Relay PPX project. Includes commands for cleaning, rebuilding, and building in watch mode.
```bash
# Quick development cycle
make rebuild # clean + build
# Build in watch mode (manual)
opam exec -- dune build --watch
# Run tests (if any)
make test
```
--------------------------------
### Create Hard-coded Newsfeed Component in ReScript
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/tutorial/3-query-basics.md
Defines a React component with hard-coded placeholder story data. Demonstrates the initial state before implementing GraphQL data fetching. Uses ReScript record types and React component syntax.
```rescript
@react.component
let make = () => {
let story: Story.story = {
title: "Placeholder Story",
summary: "Placeholder data, to be replaced with data fetched via GraphQL",
poster: {
name: "Placeholder Person",
profilePicture: Some({
url: "/assets/cat_avatar.png",
}),
},
thumbnail: Some({
url: "/assets/placeholder.jpeg",
}),
}
}
```
--------------------------------
### Setting up Relay Environment in ReScript
Source: https://context7.com/zth/rescript-relay/llms.txt
This snippet configures the Relay environment for handling network requests and data caching. It defines a fetch function using the Fetch API, creates a network layer and store, then assembles the environment. Dependencies include RescriptRelay, Fetch, and JSON handling; inputs are operation details and variables, outputting a usable environment object for React context. Limitations: Assumes a GraphQL endpoint at localhost:4000; server-side rendering requires isServer=true.
```rescript
// RelayEnv.res
open RescriptRelay
// Define network fetch function
let fetchQuery: Network.fetchFunctionPromise = async (
operation,
variables,
_cacheConfig,
_uploadables,
) => {
let response = await Fetch.fetch(
"http://localhost:4000/graphql",
{
method: #POST,
body: JSON.stringify({
"query": operation.text,
"variables": variables,
}),
headers: Headers.fromObject({
"content-type": "application/json",
"accept": "application/json",
}),
},
)
await Response.json(response)
}
// Create network layer
let network = Network.makePromiseBased(~fetchFunction=fetchQuery, ())
// Create store with record source
let store = Store.make(
~source=RecordSource.make(),
~gcReleaseBufferSize=10,
)
// Create environment
let environment = Environment.make(
~network,
~store,
~isServer=false,
)
// Inject into React app
// In Index.res:
ReactDOM.renderToElementWithId(
,
"root",
)
```
--------------------------------
### ConnectionHandler: Get Connection (ReScript)
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/api-reference.md
Retrieves a connection RecordProxy associated with a given record, key, and optional filters.
```rescript
let getConnection: (
~record: RecordProxy.t,
~key: string,
~filters: arguments=?
) => option
```
--------------------------------
### RecordSourceSelectorProxy: Get Root Record (ReScript)
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/api-reference.md
Retrieves the root RecordProxy from the RecordSourceSelectorProxy. This record holds the top-level fields.
```rescript
let getRoot: t => RecordProxy.t
```
--------------------------------
### Configure Route Preloading in ReScript Relay Router
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/making-queries.md
Configures rescript-relay-router to preload both code and data in parallel. Uses prepareCode for code splitting, prepare to call the load function with environment and variables, and render to pass the queryRef to the component. Enables optimal performance by eliminating loading waterfalls.
```rescript
module SomeComponent = %relay.deferredComponent(SomeComponent.make)
let renderer = Routes.SomeRoute.Route.makeRenderer(
~prepareCode=_ => [SomeComponentQuery.preload()],
~prepare=({environment, userId}) => {
SomeComponentQuery_graphql.load(
~environment,
~variables={userId: userId},
~fetchPolicy=StoreOrNetwork,
)
},
~render=props => {
},
)
```
--------------------------------
### RecordProxy: Get Boolean Value (Rescript)
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/api-reference.md
Retrieves the value of a field, expecting it to be a boolean. Optional arguments can be provided.
```rescript
let getValueBool: (t, ~name: string, ~arguments: arguments=?) => option
```
--------------------------------
### Defining and Using ReScript Relay Fragments
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/tutorial/4-fragments.md
Shows how to define fragments using %relay template strings, use the use hook to retrieve data, and spread fragments across different components. Demonstrates creating a reusable Image component that can work with data from different graph locations like thumbnails and profile pictures.
```ReScript
module Fragment = %relay(`
fragment Image_image on Image {
url
}
`)
@react.component
let make = (~image, ~width=?, ~height=?, ~className=?) => {
let data = Fragment.use(image)
}
```
```ReScript
module StoryFragment = %relay(`
fragment Story_story on Story {
title
summary
postedAt
poster {
...PosterByline_actor
}
thumbnail {
// change-line
...Image_image
}
}
`)
...
@react.component
let make = (~story) => {
...
// change-line
...
```
```ReScript
module PosterBylineFragment = %relay(`
fragment PosterBylineFragment on Actor {
name
profilePicture {
// change-line
...Image_image
}
}
`)
...
@react.component
let make = (~poster) => {
...
// change-line
{name->React.string}
...
```
--------------------------------
### Implement React Transition for UI Feedback
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/tutorial/9-connections-pagination.md
This Rescript code demonstrates how to use React's experimental `useTransition` hook to provide immediate visual feedback (like a spinner) while new data is being loaded. It wraps the data fetching logic (`loadNext`) within `startTransition` to allow React to prioritize updates, preventing UI jank if the user navigates away.
```rescript
@react.component
let make = (~story) => {
// change-line
let (isPending, startTransition) = ReactExperimental.useTransition()
let {data, loadNext, isLoadingNext} = StoryCommentsSectionFragment.usePagination(story)
let hasNextPage =
data.comments
->Option.flatMap(c => c.pageInfo->Option.flatMap(p => p.hasNextPage))
->Option.getWithDefault(false)
// change
let onLoadMore = () =>
startTransition(() => {
loadNext(~count=3)->RescriptRelay.Disposable.ignore
})
// end-change
{comments
->Array.map(comment => )
->React.array}
{switch hasNextPage {
| false => React.null
// change-line
| true =>
}}
// change-line
{isLoadingNext || isPending ? : React.null}
}
```
--------------------------------
### RecordSourceSelectorProxy: Get Record by ID (ReScript)
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/api-reference.md
Retrieves a record by its dataId from the RecordSourceSelectorProxy. Returns an option containing the RecordProxy if found.
```rescript
let get: (t, ~dataId: dataId) => option
```
--------------------------------
### RecordSourceSelectorProxy: Get Plural Root Field (ReScript)
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/api-reference.md
Retrieves the plural root field from a RecordSourceSelectorProxy. This is the plural version of RecordSourceSelectorProxy.getRootField.
```rescript
let getPluralRootField: (t, ~fieldName: string) => option>>
```
--------------------------------
### RecordProxy: Get Integer Value (Rescript)
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/api-reference.md
Retrieves the value of a field, expecting it to be an integer. Supports optional query arguments.
```rescript
let getValueInt: (t, ~name: string, ~arguments: arguments=?) => option
```
--------------------------------
### RecordProxy: Get Boolean Array Value (Rescript)
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/api-reference.md
Retrieves the value of a field, expecting it to be an array of booleans. Optional arguments can be used.
```rescript
let getValueBoolArray: (
t,
~name: string,
~arguments: arguments=?
) => option>>
```
--------------------------------
### Define GraphQL Query with ReScript Relay
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/tutorial/3-query-basics.md
Creates a GraphQL query using ReScriptRelay's %relay tag. Queries topStory with nested fields for poster and thumbnail data. Follows Relay naming conventions for query modules.
```rescript
// color1
module NewsfeedQuery = %relay(`
// color2
query NewsfeedQuery {
topStory {
// color3
title
// color3
summary
// color4
poster {
name
profilePicture {
url
}
}
thumbnail {
url
}
}
}
`)
```
--------------------------------
### RecordProxy: Get Float Value (Rescript)
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/api-reference.md
Retrieves the value of a field, expecting it to be a float. Optional arguments can be included for query parameters.
```rescript
let getValueFloat: (t, ~name: string, ~arguments: arguments=?) => option
```
--------------------------------
### RecordProxy: Get Integer Array Value (Rescript)
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/api-reference.md
Retrieves the value of a field, expecting it to be an array of integers. Optional arguments can be provided.
```rescript
let getValueIntArray: (
t,
~name: string,
~arguments: arguments=?
) => option>>
```
--------------------------------
### Use useLoader in Parent Component
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/tutorial/6-queries-for-interaction.md
Demonstrates setting up `useLoader` in the parent component to create a query reference and a function to initiate the query. The query reference is passed down to the child component.
```rescript
@react.component
let make = (~poster) => {
let data = Fragment.use(poster)
let hoverRef = React.useRef(Js.Nullable.null)
let (
hovercardQueryRef,
loadHoverCardQuery,
_,
) = PosterDetailsHovercardContents.HovercardQuery.useLoader()
switch data {
| None => React.null
| Some({id, name, profilePicture}) =>
}
}
```
--------------------------------
### Configure Relay Environment for Subscriptions in ReScript
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/subscriptions.md
This code sets up a subscription client and defines a subscription function for the Relay network, adapting the official Relay documentation example. Purpose is to enable WebSocket subscriptions alongside queries. Dependencies: SubscriptionsTransportWs, rescript-relay, fetchQuery function. Inputs: GraphQL config, variables; outputs: Observable for subscription data. Limitations: Assumes localhost server; requires proper token for fetch.
```rescript
/* RelayEnv.res */
let subscriptionClient = SubscriptionsTransportWs.createSubscriptionClient(
"ws://localhost:4000/graphql",
{"reconnect": true},
)
let subscriptionFunction: RescriptRelay.Network.subscribeFn = (config, variables, _cacheConfig) => {
let query = config.text->Nullable.getOr("")
let subscriptionQuery: SubscriptionsTransportWs.operationOptions = {
query: query,
variables: variables,
}
RescriptRelay.Observable.make(sink => {
let observable = subscriptionClient["request"](subscriptionQuery)
let subscription = observable["subscribe"](sink)
Some(subscription)
})
}
let network = RescriptRelay.Network.makePromiseBased(
~fetchFunction=fetchQuery(token),
~subscriptionFunction
)
let store = {
open RescriptRelay
Store.make(~source=RecordSource.make())
}
let environment = RescriptRelay.Environment.make(~network, ~store)
```
--------------------------------
### GraphQL union type definition
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/unions.md
Example GraphQL schema showing a union type (Owner) that can be either User or Group, and a query field that returns this union.
```graphql
type User {
id: ID!
firstName: String!
lastName: String!
}
type Group {
id: ID!
name: String!
}
union Owner = User | Group
type Query {
roomOwner(roomId: ID!): Owner
}
```
--------------------------------
### Rescript Component Rendering Nodes and Load More Button
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/tutorial/9-connections-pagination.md
This snippet demonstrates rendering the nodes of a connection and a load more button in a Rescript component, simplifying the logic with the `getConnectionNodes` helper.
```rescript
{comments
->Array.map(comment => )
->React.array}
{switch hasNextPage {
| Some(true) =>
| Some(false) | None => React.null
}}
```
--------------------------------
### Implement preloadable query with deferred component
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/making-queries.md
Shows how to use %relay.deferredComponent with preloadable query loading for improved performance. The pattern enables query preloading outside of React render cycle. Requires Routes module and Relay environment. The example demonstrates renderer creation with preload function and prepared query data injection.
```ReScript
module SomeComponent = %relay.deferredComponent(SomeComponent.make)
let renderer = Routes.SomeRoute.Route.makeRenderer(
~prepareCode=_ => [SomeComponentQuery.preload()],
~prepare=({environment, userId}) => {
// color2
SomeComponentQuery_graphql.load(
// change-line
SomeComponentQuery_preloadable_graphql.load(
~environment,
~variables={userId: userId},
~fetchPolicy=StoreOrNetwork,
)
},
~render=props => {
},
)
```
--------------------------------
### RecordSourceSelectorProxy: Get Root Field (ReScript)
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/api-reference.md
Retrieves a specific RecordProxy for a field at the root level. It's recommended to use RecordSourceSelectorProxy.getRoot() and traverse from there.
```rescript
let getRootField: (t, ~fieldName: string) => option
```
--------------------------------
### RecordProxy: Get Float Array Value (Rescript)
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/api-reference.md
Retrieves the value of a field, expecting it to be an array of floats. Supports optional query arguments.
```rescript
let getValueFloatArray: (
t,
~name: string,
~arguments: arguments=?
) => option>>
```
--------------------------------
### Commit Local Payload for BlogPostDraft in RescriptRelay
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/interacting-with-the-store.md
This Rescript function `setupBlogPostDraft` uses `Query.commitLocalPayload` to insert a new `BlogPostDraft` into the Relay store. It generates a unique client ID for the draft and initializes title and content as empty strings. This function requires a Relay environment as input.
```rescript
// Draft.res (continued)
let setupBlogPostDraft = (environment) => {
Query.commitLocalPayload(
~environment,
~variables=(),
~payload={
blogPostCurrentlyEditing: {
id: RescriptRelay.generateUniqueClientID(),
title: Some(""),
content: Some(""),
}
}
)
}
```
--------------------------------
### Render Newsfeed Stories using Fragment Hook
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/tutorial/9-connections-pagination.md
Renders the newsfeed stories using the Relay fragment hook (`use`) and `getConnectionNodes` helper. It maps over the story nodes to display individual stories, passing necessary props.
```rescript
@react.component
let make = (~viewer as viewerRef) => {
let contents = Fragment.use(viewerRef)
let stories = Fragment.getConnectionNodes(contents.newsfeedStories)
<>
{stories
->Array.map(story => )
->React.array}
>
}
```
--------------------------------
### RecordProxy: Get String Value (Rescript)
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/api-reference.md
Retrieves the value of a field, expecting it to be a string. Optional arguments can be provided to specify query arguments.
```rescript
let getValueString: (t, ~name: string, ~arguments: arguments=?) => option
```
--------------------------------
### GraphQL Mutation with Fragments
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/mutations.md
Example GraphQL schema demonstrating a mutation that includes nested fragments. This structure highlights the complexity that @raw_response_type aims to simplify by flattening the response.
```graphql
fragment Avatar_user on User {
id
avatarUrl
firstName
}
fragment SomeComponent_user on User {
id
firstName
lastName
...Avatar_user
}
fragment SomeOtherComponent_blogPost on BlogPost {
id
title
author {
id
firstName
...SomeComponent_user
}
}
mutation AddBlogPost($input: AddBlogPostInput!) {
addBlogPost(input: $input) {
addedBlogPost {
id
title
...SomeOtherComponent_blogPost
}
}
}
```
--------------------------------
### Using @exhaustive directive in RescriptRelay
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/unions.md
Shows how to use the @exhaustive directive to enforce compile-time checks for handling all union members. Includes basic usage and parameter examples.
```rescript
/* RoomOwner.res */
module Query = %relay(
`
query RoomOwnerQuery($roomId: ID!) {
roomOwner(roomId: $roomId) @exhaustive {
__typename
... on User {
firstName
lastName
}
... on Group {
name
}
}
}
`
)
```
```rescript
/* Ignore the Group type in exhaustiveness checking */
roomOwner(roomId: $roomId) @exhaustive(ignore: ["Group"]) {
__typename
... on User {
firstName
lastName
}
}
```
```rescript
/* Temporarily disable exhaustiveness checking */
roomOwner(roomId: $roomId) @exhaustive(disabled: true) {
__typename
... on User {
firstName
lastName
}
}
```
--------------------------------
### RecordProxy: Get String Array Value (Rescript)
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/api-reference.md
Retrieves the value of a field, expecting it to be an array of strings. Optional arguments can be used for query parameters.
```rescript
let getValueStringArray: (
t,
~name: string,
~arguments: arguments=?
) => option>>
```
--------------------------------
### Rescript Fragment with usePagination Hook
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/tutorial/9-connections-pagination.md
This snippet demonstrates using the `usePagination` hook to simplify pagination in a Rescript component. The hook returns both the data and a `loadNext` function for loading more data.
```rescript
let {data, loadNext} = Fragment.usePagination(story)
let onLoadMore = () => loadNext(~count=3)->RescriptRelay.Disposable.ignore
```
--------------------------------
### RecordProxy: Get Type Name (Rescript)
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/api-reference.md
Returns the `__typename` string for the current record. This is useful for identifying the specific type of data represented by the RecordProxy.
```rescript
let getType: t => string
```
--------------------------------
### Fetch node with Relay and handle multiple fragments in ReScript
Source: https://github.com/zth/rescript-relay/blob/master/rescript-relay-documentation/docs/the-node-interface.md
Shows a root node query that includes two fragments, ProfileSettings and ProfilePreview. The component switches on the variant returned by the query to render the appropriate fragment component. Utilizes ReScript's variant pattern matching with #ProfileSettings and #ProfilePreview.
```rescript
module Query = %relay(`
query UserProfileQuery($id: ID!) {
node(id: $id) {
... on User {
id
name
email
...ProfileSettings
...ProfilePreview
}
__typename
}
}
`)
@react.component
let make = (~id: string) => {
let queryData = Query.use(
~variables={
id: id,
}
)
{switch queryData.node {
| Some(#ProfileSettings(user)) =>
| Some(#ProfilePreview(user)) =>
| None => React.null
}}
}
```