首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >通过单点登录访问getInitialProps中的apolloClient

通过单点登录访问getInitialProps中的apolloClient
EN

Stack Overflow用户
提问于 2019-11-17 22:22:48
回答 2查看 2.1K关注 0票数 0

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

我的withAuth.js

代码语言:javascript
复制
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文件中使用它作为点对点,并试图在我的登录组件中访问apolloClient,希望检查一个人是否已经登录,以便重定向他们(也想知道为了使导航栏动态)

感谢你在这个问题上的帮助

EN

回答 2

Stack Overflow用户

发布于 2019-11-20 03:36:35

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

代码语言:javascript
复制
const apolloClient = (ctx.ctx.apolloClient = initApolloClient({}, { 
      getToken: () => getToken(ctx.req)}));
票数 1
EN

Stack Overflow用户

发布于 2020-08-08 15:50:38

我认为您遗漏了一件事,即当SSR为true时,返回apolloClient,同时返回PagePropsApolloCache

代码语言:javascript
复制
// Extract query data from the Apollo store
const apolloState = apolloClient.cache.extract();

return {
    ...pageProps,
    apolloState,
    // To get access to client while in SSR
    apolloClient
};
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58901404

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档