如何在React Apollo 2.0中正确地重新获取和缓存更新的数据?

时间:2018-04-13 01:57:11

标签: reactjs apollo

我一直在尝试使用从我的服务器重新获取的最新数据来更新我的缓存,但出于某种原因,我的所有旧数据都会持续存在,直到我重新启动服务器或执行类似client.resetStore()的操作。 / p>

首次启动应用时,它会在客户端缓存中存储一​​封电子邮件。然后使用此缓存的电子邮件,它将传递到服务器端查询以获取有关用户的数据。然后,我通过道具访问该数据,并将我的UI呈现为类似于#34; Welcome Ken。"。但是......如果我进入我的数据库并更改名称,请说.." Nek"手动,然后点击刷新按钮,我期待一个"欢迎Nek。"但相反,它仍然是" Ken"。我可以看到,在我的服务器端,从数据库中检索到了正确的数据,但是当我使用Apollo devtools查看我的缓存时,我可以看到它仍然是以前的数据,并且还没有更新新获取的数据。

在底部,我手工更改了DB内部的名称,后面包含了一个日志。我唯一改变的是" first_name"来自" Ken"到" Nek"这就是全部。

除了尝试使用refetch(),refetchQueries,轮询......我还试图执行另一个突变,看看它是否会在重新渲染后更新,但也没有运气。

经过一些调试后,我发现我的数据只在我重新启动节点服务器后才更新,这让我想知道我的设置配置中是否有错误做错了?因为在我的客户端,即使我清除我的缓存并进行硬刷新,或关闭我的选项卡/浏览器,它仍然抓住我的旧数据。我也没有使用持久链接。

ApolloConfig.js

const cache = new InMemoryCache();

const stateLink = withClientState({ cache, resolvers, defaults, typeDefs });

const authLink = setContext((request, prevContext) => ({
  headers: { authorization: localStorage.getItem('token') || '' }
}));

const httpLink = createHttpLink({
  uri: `${gqlUrl}graphql`
});

const link = ApolloLink.from([stateLink, authLink.concat(httpLink)]);
const client = new ApolloClient({
  link,
  cache,
  connectToDevTools: true
});

服务器端index.js

app.use(
  '/graphql',
  bodyParser.json(),
  graphqlAuthentication,
  graphqlExpress({
    schema,
    context: { loaders: createLoaders() }
  })
);

app.use('/graphiql', graphiqlExpress({ endpointURL: '/graphql' }));

DashboardContainer.js 此处的重新获取功能仅用于测试我的道具是否会更新(当调用该函数时,我确实可以在服务器端看到正确获取的数据/请求)

class DashboardContainer extends Component {

  refetch = () => {
    this.props.data.refetch();
    this.props.setUser({ variables: { user: this.props.data.user } });
  };

  render() {
    return (
      <div style={{ display: 'flex', justifyContent: 'center' }}>
        <Dashboard {...this.props} />
        <button onClick={this.refetch}>Refresh</button>
      </div>
    );
  }
}

DashboardContainer.propTypes = {};

const query = gql`
  query QUERY_USER_EMAIL($email: String!) {
    user(email: $email) {
      id
      email
      bcomm_client_id
      first_name
      last_name
      __typename
    }
  }
`;
export default compose(
  graphql(QUERY_GET_USER_EMAIL),
  graphql(query, {
    options: props => ({
      variables: { email: props.data.email },
      fetchPolicy: 'network-only'
    })
  }),
  graphql(MUTATION_UPDATE_USER, { name: 'setUser' })
)(DashboardContainer);

服务器端架构.js

 type User {
        id: ID!
        email: String
        last_login: String
        first_name: String
        last_name: String
        roles: String
        is_active: Boolean
        bcomm_client_id: ID
        bcomm_access_token: String
    }

    type Query {
        user(email: String!): User!
    }

客户端Queries.js

export const QUERY_GET_USER_EMAIL = gql`
  {
    email @client
  }
`;

服务器端日志

------- USER -------
TextRow {
  id: 15,
  last_login: null,
  first_name: 'NEK',
  last_name: 'WOW',
  roles: 'Admin',
  is_active: 1,
  email: 'hi@hi.com',
  bcomm_client_id: null,
  bcomm_access_token: null }
-------      Request (POST)     -------
{ host: 'localhost:8081',
  connection: 'keep-alive',
  'content-length': '244',
  pragma: 'no-cache',
  'cache-control': 'no-cache',
  accept: '*/*',
  origin: 'https://localhost:3000',
  authorization: '',
  'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36',
  'content-type': 'application/json',
  'accept-encoding': 'gzip, deflate, br',
  'accept-language': 'en-US,en;q=0.9,fr;q=0.8' }
{ operationName: 'QUERY_USER_EMAIL',
  variables: { email: 'hi@hi.com' },
  query: 'query QUERY_USER_EMAIL($email: String!) {\n  user(email: $email) {\n    id\n    email\n    bcomm_client_id\n    first_name\n    last_name\n    __typename\n  }\n}\n' }

client.Store console.log

ROOT_QUERY:
email: "hi@hi.com"
user: {type: "id", id: "User:15", generated: false}
user({"email":"hi@hi.com"}): {type: "id", id: "User:15", generated: false}  __typename: "AuthDefaults"
__proto__: Object
User:15:
    bcomm_client_id: null
    email: "hi@hi.com"
    first_name: "KEN"
    id: "15"
    last_name:"WOW"

1 个答案:

答案 0 :(得分:0)

如果有人还在想这里发生了什么事。我发现这是由于我用于GraphQL的DataLoaders。我没有正确设置正确的挂钩,因此DataLoaders不断向我发送缓存数据,因为它不知道我的数据库中发生的任何更改。这解释了为什么我在重新启动服务器后才看到正确的更新,因此它会清空缓存的数据。