如何在React Native中正确地将Apollo Client连接到Redux

时间:2017-10-22 03:39:41

标签: reactjs react-native apollo react-apollo apollo-client

过去几个小时我一直在研究这个问题,现在我非常接近解决这个问题。现在一切似乎都在工作,但我的组件中没有this.props.mutate,而Apollo HOC包含它。

我将Apollo作为减速器连接起来,所以在我的组件中,我希望看到this.props.apollo.mutate可用,但它不存在。

目前似乎提供了所有这些:

  

的console.log(this.props.apollo)

{"data":{},"optimistic":[],"reducerError":null}

以下是它的联系方式:

./ SRC / apolloClient.js

import { AsyncStorage } from 'react-native'
import { ApolloClient, createNetworkInterface } from 'react-apollo'

const networkInterface = createNetworkInterface({
    uri: 'http://localhost:8000/graphql',
    opts: {
        credentials: 'same-origin',
        mode: 'cors'
    }
})

// networkInterface is half baked as I haven't got this far yet
networkInterface.use([{
    async applyMiddleware(req, next) {
        if (!req.options.headers) req.options.headers = {}
        const token = await AsyncStorage.getItem('token')
        req.options.headers.authorization = token ? token : null
        next()
    }
}])

const client = new ApolloClient({
    networkInterface,
    dataIdFromObject: (o) => o.id
})

export default client

./ SRC / reducers.js

import client from './apolloClient'

export default combineReducers({
    apollo: client.reducer(),
    nav: navReducer,
    signup: signupReducer,
    auth: loginReducer,
})

./ SRC / App.js

import store from './store'
import client from './apolloClient'

const Root = () => {
    return (
        <ApolloProvider store={store} client={client}>
            <RootNavigationStack />
        </ApolloProvider>
    )
}

export default Root

哦,这是我的登录组件的底部(也是相当不完整的一半):

export default compose(
    connect(mapStateToProps, {
        initiateLogin,
        toggleRememberMe
    }),
    withFormik({
        validate,
        validateOnBlur: true,
        validateOnChange: true,
        handleSubmit: ({ tel, password }, { props }) => {
            props.apollo.mutate({
                    variables: { tel, password }
                })
                .then((res) => {
                    alert(JSON.stringify(res))
                    //const token = res.data.login_mutation.token
                    //this.props.signinUser(token)
                    //client.resetStore()
                })
                .catch((err) => {
                    alert(JSON.stringify(err))
                    //this.props.authError(err)
                })
            //props.initiateLogin({ tel, password })
        }
    }),
    graphql(LOGIN_MUTATION, { options: { fetchPolicy: 'network-only' } })
)(LoginForm)

感觉我需要一个动作创建者并手动将其映射到我的组件。我需要做些什么来运行这个松散显示的变异LOGIN_MUTATION onSubmit?

我目前对this.props.apollo包含Apollo数据的事实感到困惑,但没有mutate

我在这里看不到解决方案:http://dev.apollodata.com/react/mutations.html或者我可能会这样做 - 这是我需要关注的内容吗?

const NewEntryWithData = graphql(submitRepository, {
  props: ({ mutate }) => ({
    submit: (repoFullName) => mutate({ variables: { repoFullName } }),
  }),
})(NewEntry)

我想让它达到组件可以在需要时调用突变的程度。我也希望它可以在this.props.something上使用,所以我可以从Formik的handleSubmit函数调用它,但我愿意接受能够实现最佳声明性可扩展性的建议。

[edit]以下是我正在考虑解决的代码:

./ SRC / apolloClient.js

此文件已废弃。

./ SRC / reducers.js

我删除了Apollo reducer和客户端引用。

./ SRC / App.js

我将Apollo客户端放在根组件中。我从Nader Dabit的Medium帖子中获得了这项技术。他在GitHub回购中说明了这一点:

以下是它的实现方式:

const Root = () => {
    const networkInterface = createNetworkInterface({
        uri: 'http://localhost:8000/graphql',
        opts: {
            credentials: 'same-origin',
            mode: 'cors'
        }
    })

    networkInterface.use([{
        async applyMiddleware(req, next) {
            try {
                if (!req.options.headers) req.options.headers = {}
                const token = await AsyncStorage.getItem('token')
                req.options.headers.authorization = token || null
                next()
            } catch (error) {
                next()
            }
        }
    }])

    const client = new ApolloClient({
        networkInterface,
        dataIdFromObject: (o) => o.id
    })

    return (
        <ApolloProvider store={store} client={client}>
            <RootNavigationStack />
        </ApolloProvider>
    )
}

export default Root

1 个答案:

答案 0 :(得分:4)

当您使用compose时,您的HOC的顺序很重要。在您的代码中,您的第一个HOC(connect)添加的道具可供其后的所有HOC使用(withFormikgraphql)。由withFormik添加的道具仅适用于graphqlgraphql添加的道具不可用于其他两个HOC(只是组件本身)。

如果您将订单重新排列为compose - &gt; graphql - &gt; withFormik然后您应该可以访问props.mutate内的withFormik

此外,当您可以集成Redux和Apollo时,所有这一切都会阻止您拥有两个独立的商店。将现有商店传递给Apollo不会改变graphql HOC的API。这意味着,无论您使用何种商店,当您正确使用HOC时,您仍然会获得data道具(或mutate道具的突变)。

虽然将Apollo与Redux集成确实会将Apollo的商店暴露给您的应用程序,但您仍应像往常一样使用Apollo。在大多数情况下,这意味着使用graphql HOC和利用data.propsdata.mutate(或者如果你通过选项传递名字,你可以称之为道具)。

如果您需要直接调用Apollo客户端,请使用withApollo代替 - 这会暴露您可以使用的client道具。 apollo在您的代码中公开的connect道具只是Apollo使用的商店 - 它不是真正的客户端,因此它不会有像mutate这样的方法。它。但是,在大多数情况下,withApollo没有理由超过graphql