[Modern] RelayConnectionHandler cannot get connection (expects connection ID to end in _connection)
- Dominant language
- Rust
- Stars
- 19k
- Forks
- 1.9k
- PR merge metrics
- No merged PRs in 30d
Description
I have a page with a list of records and ability to add new ones. I have written a mutation to add the new records but am hitting an issue when updating the local store with the newly added record because Relay seems to expect the connection ID to have a particular form, and mine doesn't have that form. This is the setup
Schema:
```
input CreateWorkflowInput {
myWorkflow: WorkflowInput
clientMutationId: String
}
type CreateWorkflowPayload {
ok: Boolean
workflow: Workflow
clientMutationId: String
}
type MyMutations {
createWorkflow(input: CreateWorkflowInput!): CreateWorkflowPayload
}
interface Node {
id: ID!
}
type PageInfo {
hasNextPage: Boolean!
hasPreviousPage: Boolean!
startCursor: String
endCursor: String
}
type Query {
node(id: ID!): Node
allWorkflows(before: String, after: String, first: Int, last: Int): WorkflowConnection
workflow: Workflow
# Fetches objects given their IDs
nodes(
# The IDs of objects
ids: [ID!]!
): [Node]!
}
type Workflow implements Node {
workflowId: ID!
workflowName: String
workflowVersion: String
configId: String
createdDate: DateTime
lastUpdatedDate: DateTime
configuration: Configuration
analysisRunCollection(before: String, after: String, first: Int, last: Int): AnalysisRunConnection
id: ID!
}
type WorkflowConnection {
pageInfo: PageInfo!
edges: [WorkflowEdge]!
}
type WorkflowEdge {
node: Workflow
cursor: String!
}
input WorkflowInput {
workflowName: String
workflowVersion: String
configId: ID!
}
```
Universal Router:
```
const routes = [
{
path: '/',
query: graphql`query routerHomeQuery {
allWorkflows(first: 50) @connection(key: "Home_workflows") { ...Home_workflows }
}`, // prettier-ignore
components: () => [import(/* webpackChunkName: 'home' */ './Home')],
render: ([Home], data) => ({
title: 'Home page',
body: ,
}),
},
];
```
List page:
```
class Home extends React.Component {
render() {
return (
);
}
}
export default createFragmentContainer(
Home,
graphql`
fragment Home_workflows on WorkflowConnection {
edges {
node {
id
workflowName
workflowId
workflowVersion
configuration {
configId
config
}
}
}
}
`,
);
```
Mutation:
```
import { graphql, commitMutation } from 'react-relay';
import { ConnectionHandler } from 'relay-runtime';
import storeDebugger from 'relay-runtime/lib/RelayStoreProxyDebugger';
const mutation = graphql`
mutation CreateWorkflowMutation($myWorkflow: CreateWorkflowInput!) {
createWorkflow(input: $myWorkflow) {
workflow {
workflowName
workflowId
workflowVersion
configId
}
ok
}
}
`;
function addWorkflow(
environment,
workflowName,
workflowVersion,
configId,
callback,
) {
const variables = {
myWorkflow: {
myWorkflow: {
workflowName: workflowName,
workflowVersion: workflowVersion,
configId: configId,
},
},
};
commitMutation(environment, {
mutation: mutation,
variables: variables,
onCompleted: (response, errors) => {
console.log(response);
callback(response);
},
onError: err => console.error(err),
updater: proxyStore => {
storeDebugger.dump(proxyStore);
const createWorkflowField = proxyStore.getRootField('createWorkflow');
const newWorkflow = createWorkflowField.getLinkedRecord('workflow');
const storeRoot = proxyStore.getRoot();
const connection = ConnectionHandler.getConnection(
storeRoot,
'client:root:allWorkflows{"first":50}',
);
if (connection) {
const newEdge = ConnectionHandler.createEdge(
proxyStore,
connection,
newWorkflow,
'WorkflowEdge',
);
ConnectionHandler.insertEdgeAfter(connection, newEdge);
} else {
console.log('Connection not found');
}
storeDebugger.dump(proxyStore);
},
});
}
export default { addWorkflow };
```
The issue occurs when trying to call `ConnectionHandler.getConnection()`.
When I dump the store proxy the structure is as follows:

Namely the ID of the connection looks like this:
`__id:"client:root:allWorkflows{"first":50}"`
But when I step into the RelayConnectionHanlder.js code this is what appears to be happening:
```
function getConnection(record, key, filters) {
var handleKey = require('./getRelayHandleKey')(CONNECTION, key, null);
return record.getLinkedRecord(handleKey, filters);
}
```
The key that gets passed in is `client:root:allWorkflows{"first":50}"` which gets turned into `"__client:root:allWorkflows{"first":50}_connection"` and then the lookup fails.
What I am wondering is why does Relay expect the connection to have this specific ID format, and what is responsible for setting it up this way? How do I get my connection to have the right ID format?
Contributor guide
Assessment
This issue has not been assessed yet.