我正在构建一个简单的待办事项应用程序使用React,Apollo和react-apollo-hooks
进行钩子支持,但是useSubscription
钩子没有开火。
我知道实际后端的东西是有效的,因为我有一个graphiql应用程序设置,每当我保存todo时,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;
任何人都知道我似乎做错了什么?
对不起,我弄明白了,这对我来说是一个愚蠢的错误。问题似乎与我的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之前。
傻我。