使用 `react-apollo-hooks` 和 `useSubscription` 钩子
Posted
技术标签:
【中文标题】使用 `react-apollo-hooks` 和 `useSubscription` 钩子【英文标题】:Using `react-apollo-hooks` and `useSubscription` hook 【发布时间】:2019-09-14 19:44:34 【问题描述】:我正在使用 React、Apollo 和 react-apollo-hooks
构建一个简单的待办事项应用程序以支持钩子,但 useSubscription
钩子不会触发。
我知道实际的后端工作是有效的,因为我设置了一个 graphiql 应用程序,并且每当我保存待办事项时,todoCreated
事件就会出现在 graphiql 中。我也知道 websocket-setup 工作正常,因为查询和突变正在通过 websocket。顺便说一句,我正在使用 Elixir、Phoenix、Absinthe 作为后端的东西。
这是 Todo-app 组件:
import React, useState from 'react';
import gql from 'graphql-tag';
import useQuery, useMutation, useSubscription from 'react-apollo-hooks';
import styles from 'styles.css';
const TODO_FRAGMENT = gql`
fragment TodoFields on Todo
id
description
`;
const GET_TODOS = gql`
todos
...TodoFields
$TODO_FRAGMENT
`;
const SAVE_TODO = gql`
mutation createTodo($description: String!)
createTodo(description: $description)
...TodoFields
$TODO_FRAGMENT
`;
const DELETE_TODO = gql`
mutation deleteTodo($id: ID!)
deleteTodo(id: $id)
id
`;
const NEW_TODO_SUBSCRIPTION = gql`
subscription
todoCreated
...TodoFields
$TODO_FRAGMENT
`;
const Todos = () =>
const [inputValue, setInputValue] = useState('');
const data, error, loading = useQuery(GET_TODOS);
const saveTodo = useMutation(SAVE_TODO,
update: (proxy, mutationResult) =>
proxy.writeQuery(
query: GET_TODOS,
data: todos: data.todos.concat([mutationResult.data.createTodo]) ,
);
,
);
const deleteTodo = useMutation(DELETE_TODO,
update: (proxy, mutationResult) =>
const id = mutationResult.data.deleteTodo.id
proxy.writeQuery(
query: GET_TODOS,
data: todos: data.todos.filter(item => item.id !== id) ,
);
,
);
const subData = useSubscription(NEW_TODO_SUBSCRIPTION);
console.log(subData);
if (loading)
return <div>Loading...</div>;
;
if (error)
return <div>Error! error.message</div>;
;
return (
<>
<h1>Todos</h1>
data.todos.map((item) => (
<div key=item.id className=styles.item>
<button onClick=() =>
deleteTodo(
variables:
id: item.id,
,
);
>Delete</button>
' '
item.description
</div>
))
<input
value=inputValue
onChange=(e) => setInputValue(e.target.value)
type="text"
/>
<button onClick=() =>
saveTodo(
variables:
description: inputValue,
,
);
setInputValue('');
>Save</button>
</>
);
;
export default Todos;
这是根组件:
import React from 'react';
import ApolloProvider from 'react-apollo';
import ApolloProvider as ApolloHooksProvider from 'react-apollo-hooks';
import Todos from 'components/Todos';
import apolloClient from 'config/apolloClient';
const App = () => (
<ApolloHooksProvider client=apolloClient>
<Todos />
</ApolloHooksProvider>
);
export default App;
有人知道我做错了什么吗?
【问题讨论】:
【参考方案1】:对不起,我想通了,这是我的一个愚蠢的错误。问题似乎与我的 apolloClient 设置有关:
import split from 'apollo-link';
import getMainDefinition from 'apollo-utilities';
import ApolloClient from 'apollo-client';
import InMemoryCache from 'apollo-cache-inmemory';
import HttpLink from 'apollo-link-http';
import onError from 'apollo-link-error';
import ApolloLink from 'apollo-link';
import absintheSocketLink from 'config/absintheSocketLink';
const apolloClient = new ApolloClient(
link: ApolloLink.from([
onError(( graphQLErrors, networkError ) =>
if (graphQLErrors)
graphQLErrors.map(( message, locations, path ) =>
console.log(
`[GraphQL error]: Message: $message, Location: $locations, Path: $path`,
),
);
if (networkError) console.log(`[Network error]: $networkError`);
),
split(
// split based on operation type
( query ) =>
const definition = getMainDefinition(query);
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
);
,
new HttpLink(
uri: 'http://localhost:4000/api/graphql',
credentials: 'same-origin'
),
absintheSocketLink,
),
]),
cache: new InMemoryCache()
);
export default apolloClient;
上面代码中的错误是这一行
absintheSocketLink,
放错地方了。它应该在 HttpLink 之前。
我傻了。
【讨论】:
【参考方案2】:我遇到了同样的问题,我的订阅总是发送空数据,而且我也犯了一个愚蠢的错误。
【讨论】:
以上是关于使用 `react-apollo-hooks` 和 `useSubscription` 钩子的主要内容,如果未能解决你的问题,请参考以下文章
使用`react-apollo-hooks`和`useSubscription`钩子时如何避免“自动更新”缓存
React-Apollo-Hooks 使用Mutation 传递空变量?
将参数传递给 react-apollo-hooks useQuery
react-apollo-hooks 中的 useMutation 没有传递变量