0

I have setup my Relay environment like this:

// createRelayEnvironment.ts

let relayEnvironment

export default function initEnvironment({ records }: EnvProps) {
    // Create a network layer from the fetch function
    const network = Network.create(fetchQuery)

    const store = new Store(new RecordSource(records || {}))

    // Make sure to create a new Relay environment for every server-side request so that data
    // isn't shared between connections
    if (!(process as any).browser) {
        return new Environment({
            network,
            store
        })
    }

    // reuse Relay environment on client-side
    if (!relayEnvironment) {
        relayEnvironment = new Environment({
            network,
            store
        })
    }

    return relayEnvironment
}

and to fetch data:

class WithData extends React.Component {
        environment: Environment

        constructor(props: any) {
            super(props)
            this.environment = initEnvironment({
                records: props.queryRecords
            })
        }


        static async getInitialProps(ctx) {
            let composedInitialProps = {}
            if (ComposedComponent.getInitialProps) {
                composedInitialProps = await ComposedComponent.getInitialProps(ctx)
            }

            let queryProps = {}
            let queryRecords = {}

            const environment = initEnvironment({ records: {} })

            if (options.query) {
                const variables = options.mapProps ? options.mapProps() : {}
here
                queryProps = await fetchQuery(environment, options.query, variables)

                queryRecords = environment.getStore().getSource().toJSON()
            }

            return {
                ...ctx.query, // query info from next-router. E.g "slug"
                ...composedInitialProps,
                ...queryProps,
                queryRecords
            }
        }

        render() {
            const relay = {
                environment: this.environment
            }

            return (
                <ReactRelayContext.Provider value={{ environment: this.environment }}>
                    <ComposedComponent {...(this.props as P)} {...{ relay }} />
                </ReactRelayContext.Provider>
            )
        }
    }
}

I'm getting the following error:

Invariant Violation: RelayContext: Expected `context.relay` to be an object conforming to the `RelayContext` interface, got `[object Object]`.

This is happening with NextJS 11 and Relay v6.0.0. It was working fine on v5.0.0. These are quite old versions but I'm trying to upgrade.

From looking at the source code, this suggests the Relay environment is not the right format, but I don't see how this can be the case since I'm just following the doc's initialisation instructions

Is there something simple I'm doing wrong?

juliomalves
  • 42,130
  • 20
  • 150
  • 146
MDalt
  • 1,681
  • 2
  • 24
  • 46

1 Answers1

0

I eventually worked out what was causing this. The check that was failing was this line in the Relay source code.

When I added an empty object for variables, like this:

render() {
            const relay = {
                environment: this.environment
            }

            return (
                <ReactRelayContext.Provider value={{ environment: this.environment, variables: {}}>
                    <ComposedComponent {...(this.props as P)} {...{ relay }} />
                </ReactRelayContext.Provider>
            )
        }

it worked.

The downside is this now fails typescript checks. But I notice that in v7, the validation in the source code has now gone. So for me the solution has been to upgrade to v7 and remove the variables.

MDalt
  • 1,681
  • 2
  • 24
  • 46