This is a follow-up ticket of #4030. I basically have the following situation:
So, in my index page component I have the following export:
export default connect()(graphql(pageData, {
options: props => {
return {
variables: {
currentPath: props.url.pathname
}
};
}
})(Index));
So I need props.url.pathname in order to execute my query. However, by default this is not provided. So I had to change my _app.js file to the following:
import App, {Container} from 'next/app';
import React from 'react';
import withReduxStore from '../hoc/withReduxStore';
import withApolloClient from '../hoc/withApolloClient'
import {ApolloProvider} from 'react-apollo';
import {Provider as ReduxProvider} from 'react-redux';
// Manual app container necessary for Redux & Apollo
class AppContainer extends App {
render() {
const {Component, pageProps, reduxStore, apolloClient, url} = this.props;
const newProps = {
...pageProps,
url
};
return (
<Container>
<ApolloProvider client={apolloClient}>
<ReduxProvider store={reduxStore}>
<Component {...newProps} />
</ReduxProvider>
</ApolloProvider>
</Container>
)
}
}
export default withApolloClient(withReduxStore(AppContainer));
And my with-redux.js file to the following:
import App, {Container} from 'next/app';
import {Provider} from 'react-redux';
import {initStore} from '../store/common';
const isServer = typeof window === 'undefined';
const __NEXT_REDUX_STORE__ = '__NEXT_REDUX_STORE__';
function getOrCreateStore(initialState) {
// Always make a new store if server, otherwise state is shared between requests
if (isServer) {
return initStore(initialState)
}
// Store in global variable if client
if (!window[__NEXT_REDUX_STORE__]) {
window[__NEXT_REDUX_STORE__] = initStore(initialState)
}
return window[__NEXT_REDUX_STORE__]
}
export default App => {
return class Redux extends React.Component {
static async getInitialProps(appContext) {
const reduxStore = getOrCreateStore();
// Provide the store to getInitialProps of pages
appContext.ctx.reduxStore = reduxStore;
const url = {
asPath: appContext.ctx.asPath,
pathname: appContext.ctx.pathname,
query: appContext.ctx.query,
};
let appProps = {};
if (App.getInitialProps) {
appProps = await App.getInitialProps(appContext)
}
return {
...appProps,
url,
initialReduxState: reduxStore.getState()
}
}
constructor(props) {
super(props);
this.reduxStore = getOrCreateStore(props.initialReduxState)
}
render() {
return <App {...this.props} reduxStore={this.reduxStore}/>
}
}
}
Note that in both cases, I'm forwarding the url property as property to the actual component. It took a lot of time until I found out how I could use the url in the query variable, that there's an option to specify a callback instead of an object and basically it was only possible due to #4030.
So, my request is: Please include this in the examples or add a more detailed documentation in the examples around GraphQL mit Redux/Apollo. I think these are very common things and it would bring a big benefit to all involved people.
Since there's so much flexibility regarding the tools that can be used, it's hard to know the exact integration steps into an existing environment. For example, the next step in my case would be to integrate react-i18next which will probably be a pain since there's no example for GraphQL, Apollo, Redux and react-i18next. And every information you describe, like the one I'm requesting, helps!
So, my request is: Please include this in the examples or add a more detailed documentation in the examples around GraphQL mit Redux/Apollo. I think these are very common things and it would bring a big benefit to all involved people.
Feel free to send a pull request 馃槃
Most helpful comment
Feel free to send a pull request 馃槃