在具有动态创建路径的SSG NextJS网站上使用initialApolloState

时间:2020-10-14 17:30:56

标签: reactjs next.js apollo

我已经基于this official Vercel starter example重新配置了我的应用程序,并通过在initialApolloState中执行查询,将数据缓存并设置为getInitialProps,但是我很难弄清楚如何从每个页面上的该对象中提取数据。

我的页面是根据getStaticPaths动态创建的,该页面查询设置为查询REST API端点的GraphQL API。在我的旧配置中(不允许SSG,这就是为什么我必须重新配置),getStaticProps函数使用页面ID参数来查询具有该特定ID的数据,并获取该页面所需的所有数据,将它们设置为道具。但是,这种新设置似乎将数据设置为initialApolloState对象,并将ID附加到对象名称本身上。

例如,一个prop对象的名称为TourDossier:33887,所以当该对象在每个页面上都有唯一的名称时,我不知道如何从该对象中提取任何数据。页面道具在每个页面上都有唯一的名称,因为ID附加在道具本身上,这使得无法以一般方式访问此数据。

我想我只是失去了我如何使用阿波罗和SSG使用I上面列出的官方例如当应该提取的数据。该示例非常简单,并且在使用getStaticPaths查询中的路径中的getStaticProps和ID参数时似乎又复杂了一层。

任何帮助或文档阅读将不胜感激。

编辑:这是我动态创建的页面,它们使用getStaticPathsgetStaticProps

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;

我不确定是否应该查询高速缓存以获取页面道具,或者我应该以某种方式能够从initialApolloState中提取数据,即使对象都具有唯一性名称取决于查询的ID。

1 个答案:

答案 0 :(得分:0)

您需要在getStaticProps和React组件中进行相同的查询(包括变量)。

Apollo还在查询AND变量上缓存,因此具有不同变量的查询具有不同的缓存。

更改useQuery以在getStaticProps中包含与查询相同的变量。

const data = useQuery(GET_TOUR_DOSSIER, {
  variables: { id: router.query.id } 
});