facebook / facebook/relay

Feature request: export RelayOptimisticRecordSource to make it extensible

Open
#4,276 0 comments 3 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
19k
Forks
1.9k
PR merge metrics
No merged PRs in 30d

Description

# Problem

It is possible to extend and provide your own record source:

```ts
import { Environment, Store, RecordSource } from 'relay-runtime'

class MyRecordSource extends RecordSource {
// ...
}

export const RelayEnvironment = new Environment({
// ...
store: new Store(new MyRecordSource())})
})
```

However, it is not currently possible to easily extend or provide the [RelayOptimisticRecordSource](https://github.com/facebook/relay/blob/main/packages/relay-runtime/store/RelayOptimisticRecordSource.js#L34) to the store.

# Question

Is there a reason to keep the RelayOptimisticRecordSource internal?

# Discussion

Would it be possible to:

1. Export [RelayOptimisticRecordSource](https://github.com/facebook/relay/blob/main/packages/relay-runtime/store/RelayOptimisticRecordSource.js#L34) to make it extensible? Currently, developers have to define it from scratch and use it in a custom [Store.snapshot](https://github.com/facebook/relay/blob/main/packages/relay-runtime/store/RelayModernStore.js#L543-L545) just to make the smallest modification.
2. Accept OptimisticRecordSource in the store constructor to automatically pick the custom implementation, without having to extend the Store as in point 1.

# PRs

If this proposal is accepted, I could submit a PR for discussion point 1 (just exporting the RelayOptimisticRecordSource with a one-line change) or a PR for both discussion points.

## Motivation

To link child nodes inside connections to their parent nodes, we have to ask the server for the relationship.

```graphql
fragment myNodeSomeConnection on myNode
id: parentID # same as inside every child!
someConnection {
edges {
node {
id
parent {
id: parentID # ask for parent to set linked relationship in the relay store
}
}
}
}
}
```

To avoid repeatedly asking for the same relationship, I use my own RecordSource to link records that didn't come linked from the server. For example:

```graphql
fragment myNodeSomeConnection on myNode
...theParent
someConnection {
edges {
node {
id
theParentId # I know that this child node is linked to the parent node, by asking the parent ID, instead of the parent relationship
}
}
}
}
```

then, in my record source:

```ts
class MyRecordSource extends RecordSource {
// ...
set(dataID: DataID, record: RelayRecord): void {
this._records.set(dataID, handleRecords(record))
}
}

function handleRecords(record: RelayRecord) => {
// ... link node to parent node before writing to the store...
return record
}
```

However, I have to perform the same computation inside the RelayOptimisticRecordSource.

```ts
class MyOptimisticRecordSource implements MutableRecordSource { // <-- can't extend RelayOptimisticRecordSource because it's not exported
// ...
set(dataID: DataID, record: Record): void {
this._sink.set(dataID, handleRecords(record))
}
}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.