I'm testing out Apollo Graphql with React and I'm trying to update the local state with Apollo Graphql with a nested object. I'm running into an issue. The data returns a null
value and does not even return the value I set as a default. The only warning I see is Missing field __typename
. I'm not sure what I'm missing or if this is not how you properly set nested values with Graphql or Apollo issue. I have a code sandbox with the example I'm trying to do https://codesandbox.io/embed/throbbing-river-xwe2y
index.js
import React from "react";
import ReactDOM from "react-dom";
import ApolloClient from "apollo-boost";
import { ApolloProvider } from "@apollo/react-hooks";
import App from "./App";
import "./styles.css";
const client = new ApolloClient({
clientState: {
defaults: {
name: {
firstName: "Michael",
lastName: "Jordan"
}
},
resolvers: {},
typeDefs: `
type Query {
name: FullName
}
type FullName {
firsName: String
lastName: String
}
`
}
});
client.writeData({
data: {
name: {
firstName: "Kobe",
lastName: "Bryant"
}
}
});
const rootElement = document.getElementById("root");
ReactDOM.render(
<ApolloProvider client={client}>
<App />
</ApolloProvider>,
rootElement
);
App.js
import React from "react";
import Name from "./Name";
import { useApolloClient } from "@apollo/react-hooks";
function App() {
const client = useApolloClient();
client.writeData({
data: {
name: {
firstName: "Lebron",
lastName: "James"
}
}
});
return (
<div>
<Name />
</div>
);
}
export default App;
Name.js
import React from "react";
import { NAME } from "./Queries";
import { useApolloClient } from "@apollo/react-hooks";
const Name = async props => {
const client = useApolloClient();
const { loading, data } = await client.query({ query: NAME });
console.log(data);
return <div>Hello {data.name.firstName}</div>;
};
export default Name;
QUERIES.js
import gql from "graphql-tag";
export const GET_NAME = gql`
{
name @client {
firstName
lastName
}
}
`;
Unfortunately, Apollo Client's documentation is not good in this manner and simply starts using __typename
without properly explaining the reasoning behind it directly. I've seen other engineers struggling to understand its purpose before. As the warning is suggesting, you must pass a __typename
property to objects you write directly to the cache, as Apollo Client will use this value by default in its data normalization process internally, to save/identify the data.
On all your calls to client.writeData
, you should include a __typename
property, like:
client.writeData({
data: {
name: {
__typename: 'FullName', // this is the name of the type this data represents, as you defined in your typeDefs
firstName: 'Lebron',
lastName: 'James',
},
},
});
Also, you can't use async/await
on the render
method of your component -- in the case of function components, the main body itself, as Promises are not valid React elements. So you have two options:
client.query
to the useQuery
hook; orclient.readQuery
method which is synchronous and will return the data to you without a Promise. Note that with this method you're only able to make client-side requests, i.e if you want to request client and server fields at the same time, it won't work.