facebook / facebook/relay

[experimental] How to share data between pages where the fragment reference can't be explicitly passed?

Open
#3,210 1 comment 6 reactions 0 assignees View on GitHub
wontfix
Dominant language
Rust
Stars
19k
Forks
1.9k
PR merge metrics
No merged PRs in 30d

Description

## Lib version
`"react-relay": "0.0.0-experimental-183bdd28",`

## Problem

Page1 will fetch a list of projects, which is a relay connection
```typescript
const pageQuery = graphql`
query ProjectList_PageQuery($orgId: String!) {
...ProjectList_FragmentQuery @arguments(orgId: $orgId)
}
`

const connectionQuery = graphql`
fragment ProjectList_FragmentQuery on Query
@argumentDefinitions(
orgId: { type: "String!" }
first: { type: "Int", defaultValue: 50 }
after: { type: "String" }
last: { type: "Int" }
before: { type: "String" }
)
@refetchable(queryName: "ProjectListPaginationQuery") {
projectConnection(orgId: $orgId, first: $first, after: $after)
@connection(key: "ProjectList_projectConnection") {
edges {
node {
id
...ProjectListItem_project
}
}
}
}
`
```

Click the item of the list will go to page 2 with a project id

Page2 will display the project

### Two problems here:

1. How to reuse the data which has been fetched from Page1 for this very project on Page 2, for example the data defined in fragment `ProjectListItem_project`?
1. How to re-fetch the query so I can update both the project list and the project?

The current `useFragment` need me to pass a ref from the parent query, the problem here is: The `` page is not a children of `` page, there is a re-routing happening at the frontend.

## Workaround?

I am currently use `commitLocalUpdate` to **read** value from the store

```typescript
const [projectName, setProjectName] = React.useState('')

React.useEffect(() => {
if (!id) return
commitLocalUpdate(relayEnv, (store) => {
const projectConnection = ConnectionHandler.getConnection(
store.getRoot(),
'ProjectList_projectConnection',
)

if (!projectConnection) {
// user refreshed the page so no cache
// let's start a new request
} else {
const edges = projectConnection.getLinkedRecords('edges')

const projectEdge = edges.find((edge) => edge.getLinkedRecord('node').getDataID() === id)

const projectRecord = projectEdge.getLinkedRecord('node')

const projectName = projectRecord.getValue('name')

setProjectName(projectName)
}
})
}, [])

// use projectName to render, it is from the cache
```

I do not know if it is not ideal, since that's a lot of code...

I started to save the data to Redux to make it a lot simpler, but feel redundant since it is already in the Relay store.

a side question:

3. it happens for the `useQueryLoader` and `usePreloadedQuery`, where `usePreloadedQuery` need the queryRef from `useQueryLoader`, but when I switch between pages, I want to fetch the data needed for route 2 before leaving route 1, and I can not figure out how to do it, like construct the ref object with a new API?

### What is the Relay idiomatic way to solve these 3 problems? Thanks :)

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.