通过SSR在getInitialProps中访问apolloClient

我希望在页面加载之前通过SSR获得信息。我一直在关注此示例https://github.com/zeit/next.js/tree/canary/examples/with-apollo-auth/pages,但是注意到apolloClient在getInitialProps中不存在。

我的withAuth.js

import { ApolloClient } from 'apollo-client';
import { InmemoryCache } from 'apollo-cache-inmemory';
import { createHttpLink } from 'apollo-link-http';
import { setContext } from 'apollo-link-context';
import { ApolloProvider } from 'react-apollo';
import PropTypes from 'prop-types';
import Head from 'next/head';
import Cookies from 'js-cookie';
import fetch from 'isomorphic-unfetch';

export const withApollo = (PageComponent,{ ssr = true } = {}) => {
    const WithApollo = ({ apolloClient,apolloState,...pageProps }) => {
        const client = apolloClient || initApolloClient(apolloState,{ getToken });
        return (
            <ApolloProvider client={client}>
                <PageComponent {...pageProps} />
            </ApolloProvider>
        );
    };

    if (process.env.NODE_ENV !== 'production') {
        // Find correct display name
        const displayName = PageComponent.displayName || PageComponent.name || 'Component';

        // Warn if old way of installing apollo is used
        if (displayName === 'App') {
            console.warn('This withApollo HOC only works with PageComponents.');
        }

        // Set correct display name for devtools
        WithApollo.displayName = `withApollo(${displayName})`;

        // Add some prop types
        WithApollo.propTypes = {
            // Used for getDataFromTree rendering
            apolloClient: PropTypes.object,// Used for client/server rendering
            apolloState: PropTypes.object
        };
    }

    if (ssr || PageComponent.getInitialProps) {
        WithApollo.getInitialProps = async (ctx) => {
            const { AppTree } = ctx;
            console.log(AppTree);

            // Run all GraphQL queries in the component tree
            // and extract the resulting data
            const apolloClient = (ctx.apolloClient = initApolloClient(
                {},{
                    getToken: () => getToken(ctx.req)
                }
            ));

            const pageProps = PageComponent.getInitialProps ? await PageComponent.getInitialProps(ctx) : {};

            // Only on the server
            if (typeof window === 'undefined') {
                // When redirecting,the response is finished.
                // No point in continuing to render
                if (ctx.res && ctx.res.finished) {
                    return {};
                }

                if (ssr) {
                    try {
                        // Run all GraphQL queries
                        console.log('trying');
                        const { getDataFromTree } = await import('@apollo/react-ssr');
                        await getDataFromTree(
                            <AppTree
                                pageProps={{
                                    ...pageProps,apolloClient
                                }}
                            />
                        );
                    } catch (error) {
                        // Prevent Apollo Client GraphQL errors from crashing SSR.
                        // Handle them in components via the data.error prop:
                        // https://www.apollographql.com/docs/react/api/react-apollo.html#graphql-query-data-error
                        console.error('Error while running `getDataFromTree`',error);
                    }
                }

                // getDataFromTree does not call componentWillUnmount
                // head side effect therefore need to be cleared manually
                Head.rewind();
            }

            // Extract query data from the Apollo store
            const apolloState = apolloClient.cache.extract();

            return {
                ...pageProps,apolloState
            };
        };
    }

    return WithApollo;
};

let apolloClient = null;

/**
 * Always creates a new apollo client on the server
 * Creates or reuses apollo client in the browser.
 */
const initApolloClient = (...args) => {
    // Make sure to create a new client for every server-side request so that data
    // isn't shared between connections (which would be bad)
    if (typeof window === 'undefined') {
        return createApolloClient(...args);
    }

    // Reuse client on the client-side
    if (!apolloClient) {
        apolloClient = createApolloClient(...args);
    }

    return apolloClient;
};

const createApolloClient = (initialState = {},{ getToken }) => {
    let fetchOptions = {};
    const HTTP_ENDPOINT = 'http://localhost:4000/api';

    const httpLink = createHttpLink({
        uri: HTTP_ENDPOINT,credentials: 'same-origin',fetch,fetchOptions
    });

    const authLink = setContext((request,{ headers }) => {
        const token = getToken();
        return {
            headers: {
                ...headers,authorization: token ? `Bearer ${token}` : ''
            }
        };
    });

    return new ApolloClient({
        ssrMode: typeof window === 'undefined',// Disables forceFetch on the server (so queries are only run once)
        link: authLink.concat(httpLink),cache: new InmemoryCache().restore(initialState)
    });
};

const getToken = () => {
    return Cookies.get('token');
};

我在_app.js文件中将其用作HOC,并尝试访问我的Signin组件中的apolloClient,希望进行检查是否有人登录,以便对其进行重定向(也可以想知道如何使导航栏变得动态)

谢谢您的帮助

elai30 回答:通过SSR在getInitialProps中访问apolloClient

尝试以下代码,现在您应该可以在getInitialProps中访问apolloClient。

const apolloClient = (ctx.ctx.apolloClient = initApolloClient({},{ 
      getToken: () => getToken(ctx.req)}));
,

我认为您只是错过了一件事情,即当SSR为apolloClient时返回PagePropsApolloCache的同时返回true

// Extract query data from the Apollo store
const apolloState = apolloClient.cache.extract();

return {
    ...pageProps,apolloState,// To get access to client while in SSR
    apolloClient
};
本文链接:https://www.f2er.com/3086223.html

大家都在问