15

Im using Apollo Client, Graphcool and React. I have a working login form but I need the UI to update when the user is logged in, and I need this to happen in different components.

It seems apollo-link-state is the solution for this. My code below seems to work but Im getting this error:

Missing field CurrentUserIsLoggedIn in {} in writeToStore.js

My Apollo Client setup:

import React from 'react';
import ReactDOM from 'react-dom';

// Apollo
import { ApolloProvider } from 'react-apollo';
import { ApolloClient } from 'apollo-client';
import { HttpLink } from 'apollo-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { ApolloLink, split } from 'apollo-link';
import { withClientState } from 'apollo-link-state';
import { WebSocketLink } from 'apollo-link-ws';
import { getMainDefinition } from 'apollo-utilities';

// Components
import LoginTest from './components/App/LoginTest';

const wsLink = new WebSocketLink({
    uri: `wss://subscriptions.graph.cool/v1/XXX`,
    options: {
        reconnect: true,
    },
});

// __SIMPLE_API_ENDPOINT__ looks like: 'https://api.graph.cool/simple/v1/__SERVICE_ID__'
const httpLink = new HttpLink({
    uri: 'https://api.graph.cool/simple/v1/XXX',
});

// auth
const middlewareAuthLink = new ApolloLink((operation, forward) => {
    const token = localStorage.getItem('auth-token');
    const authorizationHeader = token ? `Bearer ${token}` : null;
    operation.setContext({
        headers: {
            authorization: authorizationHeader,
        },
    });
    return forward(operation);
});

const cache = new InMemoryCache();

const defaultState = {
    CurrentUserIsLoggedIn: {
        __typename: 'CurrentUserIsLoggedIn',
        value: false,
    },
};

const stateLink = withClientState({
    cache,
    defaults: defaultState,
    resolvers: {
        Mutation: {
            CurrentUserIsLoggedIn: (_, args) => {
                const data = {
                    CurrentUserIsLoggedIn: {
                        __typename: 'CurrentUserIsLoggedIn',
                        value: args.value,
                    },
                };
                cache.writeData({ data });
            },
        },
    },
});

const client = new ApolloClient({
    cache,
    link: ApolloLink.from([
        stateLink,
        middlewareAuthLink,

        split(
            // split based on operation type
            ({ query }) => {
                const { kind, operation } = getMainDefinition(query);
                return kind === 'OperationDefinition' && operation === 'subscription';
            },
            wsLink,
            httpLink,
        ),
    ]),
});

ReactDOM.render(
    <ApolloProvider client={client}>
        <LoginTest />
    </ApolloProvider>,
    document.getElementById('root'),
);

LoginTest.js:

import React from 'react';

import { graphql, compose } from 'react-apollo';
import gql from 'graphql-tag';

import App from './App';

const LoginTest = props => {
    if (props.LoginServerQuery.loading) return <p>Loading...</p>;

    // If the server tells us the user is logged in
    if (props.LoginServerQuery.loggedInUser) {
        // Then set the local logged in state to true
        props.CurrentUserIsLoggedInMutation({
            variables: {
                value: true,
            },
        });
    }

    return <App />;
};

const CurrentUserIsLoggedInMutation = gql`
    mutation CurrentUserIsLoggedInMutation($value: Boolean) {
        CurrentUserIsLoggedIn(value: $value) @client {
            value
        }
    }
`;

const LoginServerQuery = gql`
    query LoginServerQuery {
        loggedInUser {
            id
        }
    }
`;

const LoginTestQuery = compose(
    graphql(LoginServerQuery, { name: 'LoginServerQuery' }),
    graphql(CurrentUserIsLoggedInMutation, {
        name: 'CurrentUserIsLoggedInMutation',
    }),
)(LoginTest);

export default LoginTestQuery;

enter image description here

Evanss
  • 23,390
  • 94
  • 282
  • 505
  • can you specify line in which the error occure? – Luke Jan 31 '18 at 11:45
  • @Luke Ive uploaded a screenshot of the error to my question. I dont know how helpful the line numbers are though. – Evanss Jan 31 '18 at 11:55
  • and `writeToStore.js`, where is code of this file? – Luke Jan 31 '18 at 12:13
  • I would guess thats being called by cache.writeData but I'm not sure. – Evanss Jan 31 '18 at 12:14
  • so here: https://stackoverflow.com/questions/48005732/apollo-link-state-cache-writedata-results-in-missing-field-warning some1 had to make a return statement in his mutation method, maybe add return statement in your mutation method cause you have none – Luke Jan 31 '18 at 12:18

2 Answers2

7

At the moment, apollo-link-state requires you to return any result in your resolver function. It can be null too. This might be changed in the future.

Robin Wieruch
  • 14,900
  • 10
  • 82
  • 107
2
const stateLink = withClientState({
cache,
defaults: defaultState,
resolvers: {
    Mutation: {
        CurrentUserIsLoggedIn: (_, args) => {
            const data = {
                CurrentUserIsLoggedIn: {
                    __typename: 'CurrentUserIsLoggedIn',
                    value: args.value,
                },
            };
            cache.writeData({ data });
            return data;
        },
    },
},

try adding a return statement in your mutation. Similar problem occured here with different function: apollo-link-state cache.writedata results in Missing field warning

Luke
  • 362
  • 1
  • 4
  • 13