无法识别graphql apollo客户端中的对象获取错误



我是graphql的新手,我正在构建实时聊天应用程序。目前我正在先让它离线。使用react作为前端。

我目前正在使用apollo3缓存持久化在localStorage上缓存数据。但是我如何查询缓存数据而不是服务器(当我离线时(我也想在离线时向localStorage添加消息。

当设备联机时显示乐观响应我想将挂起的数据发送到服务器。

客户端文件夹中的我的ApolloProvider.js文件

import React from "react";
import {
ApolloClient,
InMemoryCache,
ApolloProvider as Provider,
createHttpLink,
ApolloLink,
split,
} from "@apollo/client";
import { setContext } from "@apollo/client/link/context";
import { RetryLink } from "@apollo/client/link/retry";
import { persistCache, LocalStorageWrapper } from "apollo3-cache-persist";
import { WebSocketLink } from "@apollo/client/link/ws";
import { getMainDefinition } from "@apollo/client/utilities";
import QueueLink from "apollo-link-queue";
let httpLink = createHttpLink({
uri: "http://localhost:4000/",
});
const authLink = setContext((_, { headers }) => {
const token = localStorage.getItem("token");
// return the headers to the context so httpLink can read them
return {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : "",
},
};
});
httpLink = authLink.concat(httpLink);
const wsLink = new WebSocketLink({
uri: `ws://localhost:4000/`,
options: {
reconnect: true,
connectionParams: {
Authorization: `Bearer ${localStorage.getItem("token")}`,
},
},
});
const link = new RetryLink();
const queueLink = new QueueLink();
const splitLink = split(
({ query }) => {
const definition = getMainDefinition(query);
return (
definition.kind === "OperationDefinition" &&
definition.operation === "subscription"
);
},
wsLink,
httpLink
);
const cache = new InMemoryCache();
const fun = async () =>
await persistCache({
cache,
storage: new LocalStorageWrapper(window.localStorage),
});
fun();
const client = new ApolloClient({
// link: splitLink,
link: ApolloLink.from([splitLink, queueLink, link]),
cache,
name: "chat-app",
version: "1.0.0",
queryDeduplication: false,
defaultOptions: {
watchQuery: {
fetchPolicy: "cache-and-network",
},
},
});
export default function ApolloProvider(props) {
return <Provider client={client} {...props} />;
}

我的messages.js文件

import React, { Fragment, useEffect, useState } from "react";
import { gql, useLazyQuery, useMutation, InMemoryCache } from "@apollo/client";
import { Col, Form } from "react-bootstrap";
import { useMessageDispatch, useMessageState } from "../../context/message";
import uuid from "react-uuid";
import Message from "./Message";
const SEND_MESSAGE = gql`
mutation sendMessage($uuid: String, $to: String!, $content: String!) {
sendMessage(uuid: $uuid, to: $to, content: $content) {
uuid
from
to
content
createdAt
hasSeen
hasSent
}
}
`;
const GET_MESSAGES = gql`
query getMessages($from: String!) {
getMessages(from: $from) {
uuid
from
to
content
createdAt
hasSeen
}
}
`;
export default function Messages() {
const { users } = useMessageState();
const dispatch = useMessageDispatch();
const [content, setContent] = useState("");
const selectedUser = users?.find((u) => u.selected === true);
const messages = selectedUser?.messages;
const [getMessages, { loading: messagesLoading, data: messagesData }] =
useLazyQuery(GET_MESSAGES, {
update(cache) {
cache.readFragment({});
console.log("reading");
},
});
const [sendMessage] = useMutation(SEND_MESSAGE, {
update(cache, { data: { sendMessage } }) {
cache.modify({
fields: {
getMessages(existingMsg) {
console.log(existingMsg);
const newMsgRef = cache.writeFragment({
data: sendMessage,
fragment: gql`
fragment sendNewMessage on Mutation {
uuid
to
from
content
hasSeen
hasSent
}
`,
});
return existingMsg.push(newMsgRef);
},
},
});
},
onError: (err) => console.log(err),
});
useEffect(() => {
if (selectedUser && !selectedUser.messages) {
getMessages({ variables: { from: selectedUser.username } });
}
}, [selectedUser]);
useEffect(() => {
if (messagesData) {
dispatch({
type: "SET_USER_MESSAGES",
payload: {
username: selectedUser.username,
messages: messagesData.getMessages,
},
});
}
}, [messagesData]);
const submitMessage = (e) => {
e.preventDefault();
if (content.trim() === "" || !selectedUser) return;
let id = uuid();
sendMessage({
variables: { uuid: id, to: selectedUser.username, content },
optimisticResponse: {
sendMessage: {
__typename: "Mutation",
uuid: id,
from: "User",
to: selectedUser.username,
content,
hasSent: false,
hasSeen: false,
createdAt: Date.now(),
},
},
});
setContent("");
};
// Displaying helper text and styling
let selectedChatMarkup;
if (!messages && !messagesLoading) {
selectedChatMarkup = <p className="info-text"> Select a friend</p>;
} else if (messagesLoading) {
selectedChatMarkup = <p className="info-text"> Loading..</p>;
} else if (messages.length > 0) {
selectedChatMarkup = messages.map((message, index) => (
<Fragment key={message.uuid}>
<Message message={message} />
{index === messages.length - 1 && (
<div className="invisible">
<hr className="m-0" />
</div>
)}
</Fragment>
));
} else if (messages.length === 0) {
selectedChatMarkup = (
<p className="info-text">
You are now connected! send your first message!
</p>
);
}
return (
<Col xs={10} md={8}>
<div className="messages-box d-flex flex-column-reverse">
{selectedChatMarkup}
</div>
<div>
<Form onSubmit={submitMessage}>
<Form.Group className="d-flex align-items-center">
<Form.Control
type="text"
className="message-input rounded-pill p-4 bg-secondary border-0"
placeholder="Type a message.."
value={content}
onChange={(e) => setContent(e.target.value)}
/>
<i
className="fas fa-regular fa-paper-plane fa-2x text-primary ml-2"
onClick={submitMessage}
role="button"
></i>
</Form.Group>
</Form>
</div>
</Col>
);
}

但当我尝试发送消息时,我目前遇到了这个错误

react_devtools_backend.js:3973 Invariant Violation: Could not identify object {"uuid":"4855ffc-6b7b-d7c8-a68-2ae0162f80a","from":"User","to":"Fire","content":"example text","createdAt":1648881891383,"hasSeen":false,"hasSent":false,"__typename":"Mutation"}

也从变异错误日志中获取错误

Error: Could not identify object {"__typename":"Message","uuid":"4855ffc-6b7b-d7c8-a68-2ae0162f80a","from":"Alan","to":"Fire","content":"example text","createdAt":"2022-04-02T06:44:51.807Z","hasSeen":false,"hasSent":false}

Apollo默认使用__typenameid字段来规范缓存。因此,在您的情况下,Apollo不会将您的uuid属性识别为缓存标识符。您可以更改uuiduuid属性,或将keyFields添加到InMemoryCache配置中。

最新更新