使用apollo graphql客户端时Redux服务器端渲染中断

时间:2016-12-01 18:04:54

标签: react-redux apollo

当我使用带有redux服务器端渲染的apollo提供程序时,

https://github.com/reactjs/redux/blob/master/docs/recipes/ServerRendering.md

我收到以下警告,它打破了服务器端输出

Warning: Failed context type: The context `client` is marked as required in `Apollo(Home)`, but its value is `undefined`.
    in Apollo(Home) (created by Connect(Apollo(Home)))
    in Connect(Apollo(Home)) (created by RouterContext)
    in RouterContext
    in Provider

然而,这使得客户端很好。

应用

window.webappStart = () => {
  const initialState = window.__PRELOADED_STATE__;
  const store = createStore(rootReducer, initialState);

  const client = new ApolloClient({
    networkInterface: createNetworkInterface({ uri: 'https://api.graph.cool/simple/v1/foo' }),
  });

  render(
    <ApolloProvider store={store} client={client}>
      <Router>{routes}</Router>
    </ApolloProvider>,
    document.querySelector(".js-content")
  );
};

这是样板apollo代码

import React from 'react';
import gql from 'graphql-tag';
import { graphql } from 'react-apollo';

// The data prop, which is provided by the wrapper below contains,
// a `loading` key while the query is in flight and posts when it is ready
function PostList({ data: { loading, posts } }) {
  if (loading) {
    return <div>Loading</div>;
  } else {
    return (
      <ul>
        {posts.map(post =>
          <li key={post.id}>
            {post.title} by {' '}
            {post.author.firstName} {post.author.lastName} {' '}
            ({post.votes} votes)
          </li>
        )}
      </ul>
    );
  }
}

// The `graphql` wrapper executes a GraphQL query and makes the results
// available on the `data` prop of the wrapped component (PostList here)
export default graphql(gql`
  query allPosts {
    posts {
      id
      title
      votes
      author {
        id
        firstName
        lastName
      }
    }
  }
`)(PostList);

1 个答案:

答案 0 :(得分:1)

对于我来说,PostList组件看起来没问题,应用程序的客户端启动也是如此。

如果您在服务器日志中收到该错误,那么我认为您希望检查您的路由中间件,以确保在呈现您的客户端之前将客户端传递给ApolloProvider应用

我正在使用Express v4。*和react-router v4。我的设置如下:

&#13;
&#13;
import React from 'react'
import { renderToString } from 'react-dom/server'
import { match, RouterContext } from 'react-router'
import ApolloClient, { createNetworkInterface } from 'apollo-client'
import { ApolloProvider, renderToStringWithData } from 'react-apollo'
import routes from '../app/routes.js'
import { store } from 'app/store/index.js'

const Html = ({ title = 'App', content }) => (
  <html>
    <head>
      <title>{title}</title>
      <link href="/main.css" rel="stylesheet"/>
    </head>
    <body>
      <div id="root" dangerouslySetInnerHTML={{ __html: content }} />
      <script src='/index.js'/>
    </body>
  </html>
)

module.exports = (req, res) => {
  match(
    {
      location: req.originalUrl,
      routes,
    },
    (error, redirectLocation, renderProps) => {
      if (redirectLocation) {
        res.redirect(redirectLocation.pathname + redirectLocation.search)
      } else if (error) {
        console.error('ROUTER ERROR:', error)
        res.status(500)
      } else if (renderProps) {
        const client = new ApolloClient({
          ssrMode: true,
          networkInterface: createNetworkInterface({
            uri: 'http://localhost:8888/graphql',
          }),
        })

        /**
         * Make sure client is added here. Store is optional */
        const App = (
          <ApolloProvider client={client} store={store}>
            <RouterContext {...renderProps} />
          </ApolloProvider>
        )

        /**
         * Render and send response
         */
        renderToStringWithData(App).then(content => {
          const html = <Html content={content}/>

          res.status(200).send(`<!DOCTYPE html>\n${ renderToString(html) }`)
        }).catch((err) => console.log(`INITIAL RENDER (SSR) ERROR:`, err))
      } else {
        res.status(404).send('Not found')
      }
    }
  )
}
&#13;
&#13;
&#13;