I have just set up graphql on my server and wanting to connect Apollo to my frontend.
I was able to integrate Apollo with Redux (How to pass initial state to reducer) but now want to map state to props via redux connect.
My current Home component looks like this:
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { graphql } from 'react-apollo';
import './Home.css'
class Home extends Component {
render() {
return (
<section className='home-container'>
<h1>Site Name</h1>
</section>
)
}
}
const mapStateToProps = state => ({
curPage: state.curPage
})
export default connect(
mapStateToProps,
)(Home)
I essentially want to replace mapStateToProps with mapQueryToProps however I am unsure how this works.
Does this make a request to my /graphql endpoint and map the response to curPage?
Will this happen before the first render? As in will this.props.curPage be available within componentWillMount()? (I need this for seo purposes to make sure all the content is rendered server side).
Where do I configure my graphql endpoint? I see some examples configuring it within their store. My store is split into store.js and index.js slightly but is as follows:
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { BrowserRouter } from 'react-router-dom';
import App from './containers/App/App';
import initialState from './initialState';
import configureStore from './store';
import { ApolloClient, ApolloProvider } from 'react-apollo';
const client = new ApolloClient();
// Let the reducers handle initial state
initState() // eslint-disable-line
// if we are in production mode, we get the initial state from the window object, otherwise, when we are in dev env we get it from a static file
const preloadedState = window.__INITIAL_STATE__ === '{{__PRELOADEDSTATE__}}' ? initialState : window.__INITIAL_STATE__
const store = configureStore(preloadedState)
ReactDOM.render(
<ApolloProvider store={store} client={client}>
<BrowserRouter>
<App />
</BrowserRouter>
</ApolloProvider>,
document.getElementById('root')
)
// store.js
import { createStore, applyMiddleware, compose } from 'redux'
import { createLogger } from 'redux-logger'
import reducers from './reducers'
import { ApolloClient } from 'react-apollo';
const logger = createLogger()
const client = new ApolloClient();
export default function configureStore(initialState = {}) {
// Create the store with two middlewares
const middlewares = [
// sagaMiddleware
logger,
client.middleware()
]
const enhancers = [
applyMiddleware(...middlewares)
]
const store = createStore(
reducers,
initialState,
compose(...enhancers)
)
// Extensions
store.asyncReducers = {} // Async reducer registry
return store
}
Update
I am now importing my client from my store so that I only have one instance of my client. I am also using /graphql as my endpoint so I shouldn't need to configure the endpoint.
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { BrowserRouter } from 'react-router-dom';
import App from './containers/App/App';
import initialState from './initialState';
import {configureStore, client} from './store';
import { ApolloClient, ApolloProvider } from 'react-apollo';
initState() // eslint-disable-line
// if we are in production mode, we get the initial state from the window object, otherwise, when we are in dev env we get it from a static file
const preloadedState = window.__INITIAL_STATE__ === '{{__PRELOADEDSTATE__}}' ? initialState : window.__INITIAL_STATE__
const store = configureStore(preloadedState)
ReactDOM.render(
<ApolloProvider store={store} client={client}>
<BrowserRouter>
<App />
</BrowserRouter>
</ApolloProvider>,
document.getElementById('root')
)
Still a bit confused about graphql(MY_QUERY, { props: mapQueryToProps })(Home)
I have a query to get curPage which works in graphiql: (I'm guessing MY_QUERY should be equal to this?)
query {
findResource(filter: {resource: "pages", slug: "about"}) {
id
title
slug
path
sections
}
}
and returns:
{
"data": {
"findResource": [
{
"id": "5",
"title": "About",
"slug": "about",
"path": "/about",
"sections": [
{
"type": "masthead",
"mh_title": "",
"video": false,
"image": [],
"showCta": false,
"cta": []
},
{
"type": "text_image",
"alignment": "left",
"text_image": [
{
"type": "text",
"title": "",
"content": "",
"call_to_action": false,
"cta": []
}
]
}
]
}
]
}
}
Would that mean my
const mapQueryToProps = ({data: { getPage: { page } }, ownProps}) => ({ curPage: page })
should look like:
const mapQueryToProps = ({data: { findResource: { page } }, ownProps}) => ({ curPage: page })