mirror of
https://github.com/terribleplan/next.js.git
synced 2024-01-19 02:48:18 +00:00
a450502a0d
* [fix] with-apollo: Cannot read property 'data'
When we create the initial serverState, we need to create the
eventual construct of the Apollo Data to reside within
Later in the constructor this allows for the initApollo to either
be generated from SSR, or to init from scratch.
Fixes
> Cannot read property 'data' of undefined
> TypeError: Cannot read property 'data' of undefined
* [refactor] with-apollo: reduce init `serverState`
No need to explicitly set `data` as empty.
This trims up 4 lines. 😀️
79 lines
2.4 KiB
JavaScript
79 lines
2.4 KiB
JavaScript
import React from 'react'
|
|
import PropTypes from 'prop-types'
|
|
import { ApolloProvider, getDataFromTree } from 'react-apollo'
|
|
import Head from 'next/head'
|
|
import initApollo from './initApollo'
|
|
|
|
// Gets the display name of a JSX component for dev tools
|
|
function getComponentDisplayName (Component) {
|
|
return Component.displayName || Component.name || 'Unknown'
|
|
}
|
|
|
|
export default ComposedComponent => {
|
|
return class WithData extends React.Component {
|
|
static displayName = `WithData(${getComponentDisplayName(ComposedComponent)})`
|
|
static propTypes = {
|
|
serverState: PropTypes.object.isRequired
|
|
}
|
|
|
|
static async getInitialProps (ctx) {
|
|
// Initial serverState with apollo (empty)
|
|
let serverState = { apollo: { } }
|
|
|
|
// Evaluate the composed component's getInitialProps()
|
|
let composedInitialProps = {}
|
|
if (ComposedComponent.getInitialProps) {
|
|
composedInitialProps = await ComposedComponent.getInitialProps(ctx)
|
|
}
|
|
|
|
// Run all GraphQL queries in the component tree
|
|
// and extract the resulting data
|
|
if (!process.browser) {
|
|
const apollo = initApollo()
|
|
// Provide the `url` prop data in case a GraphQL query uses it
|
|
const url = {query: ctx.query, pathname: ctx.pathname}
|
|
try {
|
|
// Run all GraphQL queries
|
|
await getDataFromTree(
|
|
<ApolloProvider client={apollo}>
|
|
<ComposedComponent url={url} {...composedInitialProps} />
|
|
</ApolloProvider>
|
|
)
|
|
} catch (error) {
|
|
// Prevent Apollo Client GraphQL errors from crashing SSR.
|
|
// Handle them in components via the data.error prop:
|
|
// http://dev.apollodata.com/react/api-queries.html#graphql-query-data-error
|
|
}
|
|
// getDataFromTree does not call componentWillUnmount
|
|
// head side effect therefore need to be cleared manually
|
|
Head.rewind()
|
|
|
|
// Extract query data from the Apollo store
|
|
serverState = {
|
|
apollo: {
|
|
data: apollo.cache.extract()
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
serverState,
|
|
...composedInitialProps
|
|
}
|
|
}
|
|
|
|
constructor (props) {
|
|
super(props)
|
|
this.apollo = initApollo(this.props.serverState.apollo.data)
|
|
}
|
|
|
|
render () {
|
|
return (
|
|
<ApolloProvider client={this.apollo}>
|
|
<ComposedComponent {...this.props} />
|
|
</ApolloProvider>
|
|
)
|
|
}
|
|
}
|
|
}
|