I've reconfigured my app based on this official Vercel starter example and I've got it to the point where I have my data cached and set to initialApolloState
from performing the queries in getInitialProps
, but I'm having trouble figuring out how to get the extract the data from this object on each page.
My pages are dynamically created from getStaticPaths
which queries a GraphQL API that is set up to query REST API endpoints. In my old configuration (which did not allow for SSG, which is why I had to reconfigure), the getStaticProps
function used the page ID parameter to query data with that specific ID and get all the data needed for that page and set them to props. This new setup however, seems to set the data to the initialApolloState
object with the ID attached to the object name itself.
For example, one of the prop objects is named TourDossier:33887
, so I don't know how I'm supposed to extract any data from this object when it will have a unique name on each page. The page props have unique names on each page, as the ID is attached to the props themselves, which makes it impossible to access this data in a general way.
I suppose I'm just lost on how I'm supposed to extract data when using Apollo and SSG using the official example I listed above. The example is very simple and there seems to be another layer of complexity when using getStaticPaths
and the ID parameter from the path in the getStaticProps
query.
Any help or docs to read would be greatly appreciated.
edit: here is my dynamically created page(s) which use getStaticPaths
and getStaticProps
import { initializeApollo } from "../../apollo/client";
import NavBar from "../../widgets/NavBar";
import { useRouter } from "next/router";
import { useQuery } from "@apollo/client";
import {
GET_TOURS,
GET_TOUR_DOSSIER,
GET_ITIN_DOSSIER,
GET_MAP_ROUTES,
GET_MAP_ACTIVITIES,
GET_MAP_TRANSPORT,
GET_MAP_ACCOM,
} from "../../util/gql";
import TourMain from "../../widgets/TourMain";
const Tour = (props) => {
const router = useRouter();
// This returns 'undefined'.
const data = useQuery(GET_TOUR_DOSSIER);
return (
<div>
<NavBar />
// Passing these as props does not work since these objects
// all have unique IDs based on the query (eg: tourDossier:33887)
<TourMain
tour={initialApolloState.tourDossier}
itin={initialApolloState.itinDossier}
mapRoutes={initialApolloState.mapRoutes}
mapAccom={initialApolloState.mapAccom}
mapActivities={initialApolloState.mapActivities}
mapTransport={initialApolloState.mapTransport}
/>
</div>
);
};
export async function getStaticPaths() {
const apolloClient = initializeApollo();
const tours = await apolloClient.query({
query: GET_TOURS,
});
const paths = tours.data.tours.map((tour) => `/tours/${tour.id}`);
// { fallback: false } means other routes should 404.
return { paths, fallback: false };
}
export async function getStaticProps({ params }) {
const apolloClient = initializeApollo();
const tourVars = { id: params.id };
const tourDossier = await apolloClient.query({
query: GET_TOUR_DOSSIER,
variables: tourVars,
});
const itinVars = { id: tourDossier.data.tourDossier.itinerary[0].id };
await apolloClient.query({
query: GET_ITIN_DOSSIER,
variables: itinVars,
});
await apolloClient.query({
query: GET_MAP_ACCOM,
variables: itinVars,
});
await apolloClient.query({
query: GET_MAP_ACTIVITIES,
variables: itinVars,
});
const mapTransport = await apolloClient.query({
query: GET_MAP_TRANSPORT,
variables: itinVars,
});
// Parse mapTransport array to coordinate string which can be consumed
// by Mapbox Directions API.
const coords = mapTransport.data.mapTransport.map((route) =>
route
.reduce(
(str, place) =>
`${str};${place.coordinates[0]},${place.coordinates[1]}`,
""
)
.substring(1)
);
const routesVars = { coords };
await apolloClient.query({
query: GET_MAP_ROUTES,
variables: routesVars,
});
// Pass tour and itinerary data to the page via props.
return {
props: {
initialApolloState: apolloClient.cache.extract(),
},
};
}
export default Tour;
I'm not sure if I'm supposed to be querying the cache in order to get page props or I'm somehow supposed to be able to extract the data from initialApolloState
even though the objects all have unique names based on the ID of the query.
You need to make the same queries (including variables) in both getStaticProps
and React component.
Apollo caches also on query AND variables, so query with different variables has different cache.
Change useQuery
to include variables same as query in getStaticProps
.
const data = useQuery(GET_TOUR_DOSSIER, {
variables: { id: router.query.id }
});