### 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}) =>
{name->React.string}
} } ``` -------------------------------- ### 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 }} } ```