2017-07-17 80 views
0

我刚刚在我的服务器上设置了graphql,并希望将Apollo连接到我的前端。将查询映射到Apollo.js的React中

我能够将阿波罗和Redux整合在一起(How to pass initial state to reducer),但现在想通过REDX连接将状态映射到道具。

我目前的家庭成分是这样的:

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) 

我基本上是想mapQueryToProps但是我不能确定这是如何工作,以取代mapStateToProps

这是否向我的/graphql端点发出请求并将响应映射到curPage

这会在第一次呈现之前发生吗?由于this.props.curPagecomponentWillMount()内有售? (我需要这个用于seo的目的,以确保所有的内容都呈现在服务器端)。

我该在哪里配置我的graphql端点?我看到一些示例在其商店中配置它。我的店被分成store.js和index.js略,但如下:

// 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 
} 

更新

我现在从我的商店导入我的客户端,这样我只有一个客户端实例。我也使用/graphql作为我的端点,所以我不需要配置端点。

// 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') 
) 

还是有点困惑graphql(MY_QUERY, { props: mapQueryToProps })(Home)

我有一个查询来获取curPage这graphiql工作:(我猜MY_QUERY应该等于这个? )

query { 
    findResource(filter: {resource: "pages", slug: "about"}) { 
    id 
    title 
    slug 
    path 
    sections 
    } 
} 

和回报:

{ 
    "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": [] 
       } 
      ] 
      } 
     ] 
     } 
    ] 
    } 
} 

请问这意味着我的

const mapQueryToProps = ({data: { getPage: { page } }, ownProps}) => ({ curPage: page }) 

应该是这样的:

const mapQueryToProps = ({data: { findResource: { page } }, ownProps}) => ({ curPage: page }) 

回答

3

几点:

你正在创建ApolloClient的两个实例 - 一个在index.js和一个在store.js - 您可以将客户端传递给configureStore,这样您就可以使用相同的实例。

如果您的graphQL端点位于/graphql以外的任何位置,则必须使用自定义网络接口。Example from the docs

import { ApolloClient, createNetworkInterface } from 'react-apollo'; 
const networkInterface = createNetworkInterface({ 
    uri: 'http://api.example.com/graphql' 
}); 
const client = new ApolloClient({ networkInterface }); 

只需最小的设置,从您的查询的数据不会被立即可用 - 组件将安装和重新呈现一次的数据是可用的。但是,the documentation provides a couple of ways to get around that

至于查询数据如何映射到道具,重要的是要注意,阿波罗不使用connect,而是有自己的HOC。你会以类似的方式使用它:

graphql(MY_QUERY, { props: mapQueryToProps })(Home) 

分配给道具的功能将被传递一个具有两个属性,dataownProps单个对象。数据包含查询结果,ownProps指的是组件上的任何现有道具。所以你mapQueryToProps可能看起来像:

const mapQueryToProps = ({data: { getPage: { page } }, ownProps}) => 
    ({ curPage: page }) 

也可以省略指定props干脆,你会只得到了整个data对象作为道具。以上只是微调实际分配给组件的道具的一种方式。

如果还有你想用终极版为保持你的状态的部分,有一个在文档整合终极版和阿波罗的部分。如果您使用撰写或recompose,它是相当干净。

阿波罗对文档做出反应是很清楚和对这点。如果你还没有,你可能想只是去通过Setup and optionsUsage部分,甚至可能通过任何适用Recipes在进行下一步之前。

编辑:您传递给HOC的查询将需要是一个字符串。最简单的方法是导入并使用gql标签。根据您提供的查询,它看起来像这样:

const MY_QUERY = gql` 
    query { 
    findResource(filter: {resource: "pages", slug: "about"}) { 
     id 
     title 
     slug 
     path 
     sections 
    } 
    }` 
+0

好吧,我已根据您的建议对客户端进行了更改。我已经用我这样做的方式更新了我原来的帖子。其次我仍然有点不确定如何映射QueryToProps。我用另一个例子更新了我原来的帖子。我在正确的轨道上吗?我也阅读过你建议的文档。 – Stretch0

+1

请参阅我的编辑以了解如何在查询中传递。你可以阅读更多[这里](http://dev.apollodata.com/react/queries.html#basics)。至于mapQueryToProps ...在我的exampe中,我只是猜测你的数据结构是什么;查看查询返回的内容 - 这是您在mapQueryToProps中使用的数据对象。我猜你需要返回数组中的第一个对象,所以你可以做一些事情:({data})=>({curPage:data.findResource [0]})。 –

+0

或者不用担心为这样的简单情况设置道具。只要执行'graphql(MY_QUERY)(Home)',然后就可以用'props.data'访问组件内的数据。可能不那么头疼。 –