Closed Hubro closed 4 years ago
I have been completely stuck on this for hours, so I've worked around this the only way I see how - I have refactored my fragment container by extracting the list item out into a separate component. The list item is now the fragment container, not the list itself. The consequence of this is that the list itself can no longer access any of the queried data, since it's not a query fragment... So all the logic it used to do has to be moved up into the parent component, which in this case is my index page:
/*
* Dashboard page
*/
import { Typography, Container } from "@material-ui/core"
import { NextPage } from "next"
import { graphql } from "react-relay"
import NextRouter from "next/router"
import DefaultLayout from "../components/layout/DefaultLayout"
import FormInstanceList from "~/components/forms/FormInstanceList"
import FormInstanceListItemContainer from "~/components/forms/FormInstanceListItemContainer"
import withData from "~/withData"
import {
pages_dashboard_Query,
pages_dashboard_QueryResponse as QueryResponse,
} from "./__generated__/pages_dashboard_Query.graphql"
const IndexPage: NextPage<QueryResponse> = props => {
const handleOpenClick = (
formInstance: typeof props.draftFormInstances[0]
) => {
NextRouter.push(`/form-instance/${formInstance.id}`)
}
const handleEditClick = (
formInstance: typeof props.draftFormInstances[0]
) => {
NextRouter.push(`/form-instance/${formInstance.id}/edit`)
}
const { draftFormInstances, submittedFormInstances } = props
return (
<DefaultLayout>
<Container maxWidth="md">
<Typography variant="h5" style={{ marginBottom: 25 }}>
My drafts
</Typography>
<FormInstanceList>
{submittedFormInstances.length == 0 && (
<Typography style={{ padding: "20px" }}>
Nothing to display
</Typography>
)}
{draftFormInstances.length > 0 &&
draftFormInstances.map(formInstance => (
<FormInstanceListItemContainer
key={formInstance.id}
formInstance={formInstance}
onOpenClick={() => handleOpenClick(formInstance)}
onEditClick={() => handleEditClick(formInstance)}
/>
))}
</FormInstanceList>
<Typography variant="h5" style={{ marginBottom: 25 }}>
Submitted forms
</Typography>
<FormInstanceList>
{submittedFormInstances.length == 0 && (
<Typography style={{ padding: "20px" }}>
Nothing to display
</Typography>
)}
{submittedFormInstances.length > 0 &&
submittedFormInstances.map(formInstance => (
<FormInstanceListItemContainer
key={formInstance.id}
formInstance={formInstance}
onOpenClick={() => handleOpenClick(formInstance)}
onEditClick={() => handleEditClick(formInstance)}
/>
))}
</FormInstanceList>
</Container>
</DefaultLayout>
)
}
export default withData<pages_dashboard_Query>(IndexPage, {
query: graphql`
query pages_dashboard_Query {
draftFormInstances: formInstances(status: DRAFT) {
id
...FormInstanceListItemContainer_formInstance
}
submittedFormInstances: formInstances(status: SUBMITTED) {
id
...FormInstanceListItemContainer_formInstance
}
}
`,
})
This is now excruciatingly verbose... And this has to be repeated for every list I want to render. I can't move the repeated logic into the list because the list can't know anything about the queried data anymore. This is all it currently does:
import { FunctionComponent } from "react"
import { Paper, List } from "@material-ui/core"
export const FormInstanceList: FunctionComponent = ({ children }) => {
return (
<Paper>
<List dense>{children}</List>
</Paper>
)
}
export default FormInstanceList
It feels like I've butchered my code in order to get it running... Surely there must be a better way.
Alright, I sure wasted a whole lot of time for no reason. Turns out exactly what I asked in my original post already exists, I just didn't manage to find it before now:
https://relay.dev/docs/en/graphql-in-relay#relayplural-boolean
@Hubro Thank you for making this issue. You just saved me a ton of time, after spending hours already looking at the Pagination docs and other Github issues. This was not easy to find in the documentation
I have defined a fragment container that should render a list of elements:
This follows the "composing fragment containers" example from your docs: https://relay.dev/docs/en/quick-start-guide#composing-fragments
However, the docs don't mention how you would render more than one of these at the same depth. I obviously can't do this:
There also doesn't appear to be a way to use aliases to separate the queries when using fragment containers (https://github.com/facebook/relay/issues/1978).
This means that I have to move the queries out of the fragment container, so now I have:
And my main query is now:
The issue is that now my
FormInstanceListContainer
is only requesting a singleFormInstance
, not a list of them. If I try to pass it the entire list, Relay crashes with an error about invalid input (truncated):Is there any way to instruct Relay that
FormInstanceListContainer
should render a list ofFormInstance
, not just one?Am I completely lost here? Should I be taking a completely different approach that I'm not seeing?