-
Notifications
You must be signed in to change notification settings - Fork 28
Open
Description
Incremental adoption API
Overview
- We can migrate from leaf to root.
- At the root, we can control whether to make an API call to fetch REST data or GraphQL with a parameter (i.e. which can be controlled by an experiment)
- This is similar to how the relay migration API works.
Detailed migration example
- So, imagine we have two components
Root -> Leaf
. We prop drill aBlog
item down. We would first migrateLeaf
, thenRoot
. Let's talk each in turn
Migrating leaf
Leaf
component: replace it with a fieldBlog.Leaf
:
export const leaf = iso(`
field Blog.Leaf($otherVar1: String!, $otherVar2: String!) @component {
name
someOtherField(otherVar1: $otherVar1, otherVar2: $otherVar2)
}
`)(({ data, parameters }, { extraText }: { extraText: string }) => {
// ...
})
- In
Root
, call
<IsographMigrationRenderer
field={iso(`reference Blog.Leaf(otherVar1: "foo")`)} /* any omitted parameters are required */
parameters={{ otherVar2: "bar" }}
runtimeProps={{ extraText: "baz" }}
startUpdate={ /* optional, maybe unsupported at first */ }
migrationContext={...} /* more on this later */
legacyData={blog}
/>
There should be an equivalent hook-based API for non-@component's
- If we have no hard coded parameters, babel/swc can change
reference Blog.Leaf
to the default export of the reader AST. If we do have hard-coded parameters, we have to figure out where to write the artifact! This is the same problem as anonymous entrypoints Anonymous entrypoints #712. At first, we can probably disallow hard-coded parameters.
Migrating Root
- A new client field for
Query.Root
:
export const root = iso(`
field Query.Root($id: ID!) {
blog(id: $id) {
title
Leaf(otherVar1: "foo", otherVar2: "bar")
}
}
`)(({ data }) => ...)
- Replace
<IsographMigrationRenderer />
with a selection ofLeaf
and render that directly - In the
Root
React component (which was not deleted), call
const { fragmentReference } = useLazyMigrationReference(
entrypoint(iso`entrypoint Query.Root`),
/* variables */,
/* options */,
{
strategy: 'Isograph', /* or 'Legacy' */
migrationContext
}
)
and render that as usual
migrationContext
The context contains at least two functions:
- readScalarField(...)
- readLinkedField(...)
I'm not sure if we only need two functions! We may need some more, such as subscribe
, etc. (But subscriptions may just be started by read[Scalar|Linked]Field
, though)
These functions allow you to read from the legacy data (e.g. reading blog.author_name
when blog.authorName
is requested)
Perhaps we can read migrationContext from React context, instead of passing it as a variable. But my strong preference is to be explicit. Folks can write wrappers in userland if they want to read it from context!
Metadata
Metadata
Assignees
Labels
No labels