无法使用嵌套值设置阿波罗本地状态

时间:2019-09-19 00:09:24

标签: reactjs apollo apollo-client react-apollo-hooks apollo-boost

我正在使用React测试Apollo Graphql,并且尝试使用带有嵌套对象的Apollo Graphql更新本地状态。我遇到了一个问题。数据返回一个null值,甚至不返回我设置为默认值的值。我看到的唯一警告是Missing field __typename。我不确定我缺少什么,或者如果这不是您使用Graphql或Apollo问题正确设置嵌套值的方式。我有一个代码沙箱,其中包含我要尝试的示例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
    }
  }
`;

1 个答案:

答案 0 :(得分:2)

不幸的是,Apollo Client的文档在这种情况下不好用,只是开始使用__typename,而没有直接正确解释其背后的原因。我以前见过其他工程师努力了解其目的。如警告所暗示的那样,您必须将__typename属性传递给您直接写入缓存的对象,因为Apollo Client会默认在内部数据规范化过程中使用此值来保存/识别数据。

在所有对client.writeData的呼叫上,您都应包含一个__typename属性,例如:

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',
    },
  },
});

此外,您不能在组件的async/await方法上使用render -对于功能组件,主体本身,因为Promises不是有效的React元素。因此,您有两种选择:

  • client.query切换到useQuery挂钩;或
  • 由于您仅请求客户端字段,因此可以使用client.readQuery方法,该方法是同步的,将在没有Promise的情况下将数据返回给您。请注意,使用这种方法,您只能发出客户端请求,即,如果您想同时请求客户端和服务器字段,将无法正常工作。