[英]How to properly hook up Apollo Client to Redux in React Native
I've been researching this for the past couple hours, and I am now extremely close to solving this. 在过去的几个小时中,我一直在研究这个问题,现在,我已经非常接近解决这个问题了。 Everything seems to be working now, but I do not have
this.props.mutate
in my component that has the Apollo HOC wrapping it. 现在一切似乎都可以正常工作,但是我的组件中没有Apollo HOC封装的
this.props.mutate
。
I wired Apollo up as a reducer, so in my component, I would expect to see this.props.apollo.mutate
available, but it's not there. 我将Apollo
this.props.apollo.mutate
为减速器,因此在我的组件中,我希望看到this.props.apollo.mutate
可用,但它不存在。
This is all that seems to be provided currently: 目前似乎提供了这些:
console.log(this.props.apollo)
console.log(this.props.apollo)
{"data":{},"optimistic":[],"reducerError":null}
Here is how it is hooked up: 这是它的连接方式:
./src/apolloClient.js ./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 ./src/reducers.js
import client from './apolloClient'
export default combineReducers({
apollo: client.reducer(),
nav: navReducer,
signup: signupReducer,
auth: loginReducer,
})
./src/App.js ./src/App.js
import store from './store'
import client from './apolloClient'
const Root = () => {
return (
<ApolloProvider store={store} client={client}>
<RootNavigationStack />
</ApolloProvider>
)
}
export default Root
Oh, and here's the bottom of my Login component (also fairly half-baked): 哦,这是我的Login组件的底部(也是半熟):
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)
It feels like I need an action creator and to manually map it to my component. 感觉就像我需要一个动作创建者并将其手动映射到我的组件。 What do I need to do to run this loosely shown mutation
LOGIN_MUTATION
onSubmit? 我需要做什么来运行此松散显示的突变
LOGIN_MUTATION
onSubmit?
I'm currently confused by the fact this.props.apollo
has Apollo's data in it, but there is no mutate
. 目前,我对
this.props.apollo
包含Apollo的数据感到困惑,但是没有mutate
。
I don't see the solution here: http://dev.apollodata.com/react/mutations.html or maybe I do -- is this what I need to be looking at? 我在这里看不到解决方案: http : //dev.apollodata.com/react/mutations.html还是我愿意-这是我需要关注的吗?
const NewEntryWithData = graphql(submitRepository, {
props: ({ mutate }) => ({
submit: (repoFullName) => mutate({ variables: { repoFullName } }),
}),
})(NewEntry)
I'd like to get it to the point where the component can call the mutation when it needs to. 我想让组件可以在需要时调用突变。 I'd also like it to be available on
this.props.something
so I can call it from Formik's handleSubmit function, but I am open to suggestions that enable the best declarative scalability. 我也希望它可以在
this.props.something
上使用,因此我可以从Formik的handleSubmit函数中调用它,但是我愿意接受能够实现最佳声明式可伸缩性的建议。
[edit] Here is the code that I am considering solved: [编辑]这是我正在考虑解决的代码:
./src/apolloClient.js ./src/apolloClient.js
This file was scrapped. 该文件已报废。
./src/reducers.js ./src/reducers.js
I removed the Apollo reducer and client reference. 我删除了Apollo减速器和客户端参考。
./src/App.js ./src/App.js
I put the Apollo Client inside the root component. 我将Apollo Client放在根组件中。 I got this technique from Nader Dabit's Medium post.
我从Nader Dabit的Medium帖子中获得了这项技术。 He illustrates this in a GitHub repo:
他在GitHub存储库中对此进行了说明:
Here is how it looks implemented: 这是实现的样子:
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
When you use compose
, the order of your HOCs matters. 使用
compose
,HOC的顺序很重要。 In your code, the props added by your first HOC ( connect
) are available to all the HOCs after it ( withFormik
and graphql
). 在您的代码中,您的第一个HOC(
connect
)添加的道具对之后的所有HOC( withFormik
和graphql
)都是可用的。 The props added by withFormik
are only available to graphql
. withFormik
添加的道具仅可用于graphql
。 The props added by graphql
are available to neither of the other two HOCs (just the component itself). graphql
添加的道具对其他两个graphql
均不可用(仅组件本身)。
If you rearrange the order to be compose
-> graphql
-> withFormik
then you should have access to props.mutate
inside withFormik
. 如果您重新排列的顺序来
compose
- > graphql
- > withFormik
那么你应该有机会获得props.mutate
内withFormik
。
Additionally, while you can integrate Redux and Apollo, all this does is prevent you from having two separate stores. 此外,虽然您可以集成Redux和Apollo,但这样做的全部目的是防止您拥有两个单独的商店。 Passing an existing store to Apollo is not going to change the API for the
graphql
HOC. 将现有商店传递给Apollo不会更改
graphql
HOC的API。 That means, regardless of what store you're using, when you correctly use the HOC, you will still get a data
prop (or a mutate
prop for mutations). 这意味着,无论您使用什么存储,当您正确使用HOC时,您仍然会获得
data
道具(或用于突变的mutate
道具)。
While integrating Apollo with Redux does expose Apollo's store to your application, you should still use Apollo like normal. 虽然将Apollo与Redux集成确实将Apollo的商店公开给您的应用程序,但您仍应像平常一样使用Apollo。 In most cases, that means using the
graphql
HOC and utilizing data.props
and data.mutate
(or whatever you call those props if you pass in a name through options). 在大多数情况下,这意味着使用
graphql
HOC并利用data.props
和data.mutate
(或通过选项传递名称的任何方式调用这些props)。
If you need to call the Apollo client directly, then use withApollo instead -- this exposes a client
prop that you can then use. 如果您需要直接调用Apollo客户端,则改为使用withApollo -这会公开一个
client
道具,您可以随后使用它。 The apollo
prop that connect
exposes in your code is just the store used by Apollo -- it's not the actual client, so it will not have methods like mutate
available to it. 在代码中公开的
connect
apollo
道具只是阿波罗使用的商店-它不是实际的客户端,因此不会有像mutate
这样的方法可用。 In most cases, though, there's no reason to go with withApollo
over graphql
. 但是,在大多数情况下,没有理由在
withApollo
上使用graphql
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.