【问题标题】:How to properly hook up Apollo Client to Redux in React Native如何在 React Native 中正确地将 Apollo 客户端连接到 Redux
【发布时间】:2018-04-02 21:00:00
【问题描述】:

过去几个小时我一直在研究这个问题,现在我非常接近解决这个问题。现在似乎一切正常,但我的组件中没有 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 函数中调用它,但我愿意接受能够实现最佳声明式可伸缩性的建议。

[编辑] 这是我正在考虑解决的代码:

./src/apolloClient.js

此文件已废弃。

./src/reducers.js

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

./src/App.js

我将 Apollo Client 放在根组件中。我从 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

【问题讨论】:

  • 我认为options.props 是我需要的。我目前正在研究它。
  • 对于将来看到此内容的任何人,请阅读有关 AsyncStorage 的 React Native 文档。您应该创建自己的实例。不要直接使用它,因为它具有全局元素。我的代码显示是这样的,但这是因为代码未完成。

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


【解决方案1】:

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

如果您将顺序重新排列为compose -> graphql -> withFormik,那么您应该可以在withFormik 中访问props.mutate

此外,虽然您可以集成 Redux 和 Apollo,但这只是防止您拥有两个独立的商店。将现有存储传递给 Apollo 不会更改 graphql HOC 的 API。这意味着,无论您使用什么商店,当您正确使用 HOC 时,您仍然会得到一个 data 道具(或用于突变的 mutate 道具)。

虽然将 Apollo 与 Redux 集成确实会将 Apollo 的 store 暴露给您的应用程序,但您仍然应该像往常一样使用 Apollo。 在大多数情况下,这意味着使用 graphql HOC 并利用 data.props 和 @ 987654339@(或者如果你通过选项传入一个名称,那么你称之为这些道具的任何东西)。

如果您需要直接调用 Apollo 客户端,请改用 withApollo —— 这会公开一个 client 属性,然后您可以使用它。 connect 在您的代码中公开的 apollo 道具只是 Apollo 使用的商店——它不是实际的客户端,因此它不会有像 mutate 这样的方法可供使用。不过,在大多数情况下,没有理由选择 withApollo 而不是 graphql

【讨论】:

  • 很好,谢谢。考虑到 compose 实际在做什么,这是完全合理的。谢谢你的帖子;这非常有帮助。
  • 你是说我可以在我的根组件中以相同的方式传递客户端,但只需省略将其连接到 Redux 的步骤? (很确定我的网络应用程序就是这样做的)。
  • 大声笑,我只是自欺欺人。在我提交表单之前,this.props 中实际上没有任何可见的内容。我从 Redux 中删除了 Apollo,所以现在它与我的 Web 应用程序完全匹配,我刚刚收到一个网络请求错误,因为我还没有创建用户,所以它肯定可以工作。再次,您的帖子非常有帮助,谢谢。我将更新我的帖子以说明已解决的代码(对于任何未来的搜索者)。
猜你喜欢
  • 2021-07-07
  • 1970-01-01
  • 2020-06-12
  • 2020-12-05
  • 2017-04-06
  • 1970-01-01
  • 1970-01-01
  • 2021-04-26
  • 1970-01-01
相关资源
最近更新 更多