【问题标题】:Apollo request from Vuex来自 Vuex 的 Apollo 请求
【发布时间】:2020-07-28 21:55:02
【问题描述】:

谁能告诉我可以从哪里导入apolloClient 以便我可以向 apollo 发出请求? 我通常会收到一个错误,要么 mutate is not a function(即使我从 Vue 组件传入this.$apollo

我只是想进入 Vue 的方式。如果有任何关于代码和结构的提示,我将不胜感激

登录组件

<template>
  <div class="signIn-component">
    <form @submit.prevent="signInUser()">
      <input
        type="email"
        placeholder="Enter your email"
        v-model="formInput.email"
      />
      <input
        type="password"
        placeholder="Enter your password"
        v-model="formInput.password"
      />
      <button>Sign In</button>
    </form>
  </div>
</template>

<script>
import { createNamespacedHelpers } from "vuex";

const { mapActions } = createNamespacedHelpers("auth");

export default {
  data() {
    return {
      formInput: {
        email: null,
        password: null
      }
    };
  },
  methods: {
    // Vuex Actions
    ...mapActions(["signIn"]),
    signInUser: function() {
      // eslint-disable-next-line no-unused-vars
      this.signIn(this.formInput, this.$apollo).then(_ =>
        this.$route.push("/")
      );
    }
  }
};
</script>

<style></style>


Vuex.auth

import { apolloClient } from 'vue-cli-plugin-apollo/graphql-client';
import SignInGQL from "@/graphql/signIn.gql";

export default {
    namespaced: true,
    state: {
        token: null,
        user: {},
        authStatus: false
    },
    getters: {
        isAuthenticated: state => !!state.token,
        authStatus: state => state.authStatus,
        user: state => state.user
    },
    actions: {
        async signIn({ commit, dispatch }, formInput) {

            console.log('here');
            try {
                const { data } = await apollo.mutate({
                    mutation: SignInGQL,
                    variables: { ...formInput }
                })

                const { token } = data.signIn;
                console.log(token);
                commit('setToken', token);
                localStorage.setItem('auth-token', token);
                dispatch('setUser', token);
            } catch (e) {
                console.error(e)
            }
        },
        setUser({ commit }, token) {
            const encodedPayload = token.split('.')[1];

            const { payload } = JSON.parse(atob(encodedPayload));
            console.log('payload: ', payload);

            // TODO: Set User information 
            commit('signInUser', payload);
        }
    },
    mutations: {
        setToken(state, token) {
            state.token = token
        },
        signInUser(state, user) {
            state.authStatus = true
            state.user = { ...user }
        },
        // logOutUser(state) {
        //     state.authStatus = ''
        //     state.token = '' && localStorage.removeItem('auth-token')
        // }
    }
}

【问题讨论】:

    标签: vuejs2 vuex apollo vue-apollo


    【解决方案1】:

    This question explains adding headers to apollo client

    solution repo

    import { setContext } from "apollo-link-context";
    import { ApolloClient, InMemoryCache, HttpLink } from "apollo-boost";
    import VueApollo from "vue-apollo";
    
    Vue.use(VueApollo);
    const httpLink = new HttpLink({
      uri: "http://sebapi.com/graphql"
    });
    const authLink = setContext((_, { headers }) => {
      // get the authentication token from ApplicationSettings if it exists
      const token = ApplicationSettings.getString("token");
      // return the headers to the context so HTTP link can read them
      return {
        headers: {
          ...headers,
          authorization: token ? `Bearer ${token}` : null
        }
      };
    });
    // update apollo client as below
    const apolloClient = new ApolloClient({
      link: authLink.concat(httpLink),
      cache: new InMemoryCache()
    });
    
    const apolloProvider = new VueApollo({
      defaultClient: apolloClient
    });
    

    和 LOGIN.VUE

    <script lang="ts">
    
    export default {
      data() {
        return {
          jwt: "",
          user: {
            identifier: "test",
            password: "123123",
          },
        };
      },
      methods: {
        handleLogin() {
    
          request({
            url: "http://sebapi.com/auth/local",
            method: "POST",
            headers: { "Content-Type": "application/json" },
            content: JSON.stringify({
              identifier: this.user.identifier,
              password: this.user.password,
            }),
          })
            .then(
              (response) => {
                const result = response.content.toJSON();
                console.log("Result from Server: ", result);
    //ignore applicationsettings it's just a kind of localstore in nativescript
                ApplicationSettings.setString("token", result.jwt);           
              },
              (e) => {
                console.error(e);
    //ignore nativateto its routing in nativescript
                this.$navigateTo(routes.login);
              }
            )
            .then(() => {
              this.$navigateTo(routes.app);
            });
        },
      },
    };
    </script>
    
    

    【讨论】:

    • 默认情况下,Vue-Apollo 文件导出函数“createProvider”(如果您使用 Vue Apollo 的 cli 版本)。而持有 ApolloClient 的“createApolloClient”在“createRrovider”中被声明。我将 createApolloClient 移到了 CreateProvider 之外,将其导出到那里,然后将其导入到我的商店文件中。默认情况下,标题是在后台实现的。我只是简单地添加了我保存令牌的 localStorage 文件的名称。我在 Vuex 存储中使用 Apollo 时遇到了麻烦。我不想修补自己的实现,因为我使用了 Vue-Apollo
    • 您是否使用其他路由器而不是 Vue 内置路由器?我注意到“this.$navigateTo”。或者您只是全局分配了自己的导航服务?我是这个框架的新手——很多关于实践和经验的问题
    • @Valaryo 这只是在 nativescript-vue 中导航的另一种方式Manual routing
    • 我知道了。谢谢!
    【解决方案2】:

    我就是这样做的,以防有人正在寻找相同的答案:

    import Vue from 'vue'
    import VueApollo from 'vue-apollo'
    import { createApolloClient } from 'vue-cli-plugin-apollo/graphql-client'
    
    // Install the vue plugin
    Vue.use(VueApollo)
    
    // Name of the localStorage item
    const AUTH_TOKEN = 'auth-token'
    
    // Http endpoint
    const httpEndpoint = process.env.VUE_APP_GRAPHQL_HTTP || 'http://localhost:3000/graphql';
    
    // Config
    const defaultOptions = {
      // You can use `https` for secure connection (recommended in production)
      httpEndpoint,
      // You can use `wss` for secure connection (recommended in production)
      // Use `null` to disable subscriptions
      wsEndpoint: process.env.VUE_APP_GRAPHQL_WS || null,
      // wsEndpoint: process.env.VUE_APP_GRAPHQL_WS || 'ws://localhost:3000/graphql',
      // LocalStorage token
      tokenName: AUTH_TOKEN,
      // Enable Automatic Query persisting with Apollo Engine
      persisting: false,
      // Use websockets for everything (no HTTP)
      // You need to pass a `wsEndpoint` for this to work
      websocketsOnly: false,
      // Is being rendered on the server?
      ssr: false,
    
      // Override default apollo link
      // note: don't override httpLink here, specify httpLink options in the
      // httpLinkOptions property of defaultOptions.
      // httpLinkOptions: {
      //   headers: {
      //     Authorization: authHeader
      //   }
      // }
    
      // Override default cache
      // cache: myCache
    
      // Override the way the Authorization header is set
      // getAuth: (tokenName) => getUserToken(),
    
      // Additional ApolloClient options
      // apollo: { ... }
    
      // Client local data (see apollo-link-state)
      // clientState: { resolvers: { ... }, defaults: { ... } }
    }
    
    export const { apolloClient, wsClient } = createApolloClient({
      ...defaultOptions,
      // ...options,
    })
    
    // Call this in the Vue app file
    export function createProvider() {
      // Create apollo client
    
      apolloClient.wsClient = wsClient
    
      // Create vue apollo provider
      const apolloProvider = new VueApollo({
        defaultClient: apolloClient,
        defaultOptions: {
          $query: {
            fetchPolicy: 'cache-and-network',
          },
        },
        errorHandler(error) {
          // eslint-disable-next-line no-console
          console.log('%cError', 'background: red; color: white; padding: 2px 4px; border-radius: 3px; font-weight: bold;', error.message)
        },
      })
    
      return apolloProvider
    }
    
    
    

    This is the source I found the solution

    如果您有任何建议,请随时将它们留在此处!

    【讨论】:

      猜你喜欢
      • 2019-12-21
      • 2019-07-23
      • 2022-01-06
      • 2019-07-26
      • 2022-07-28
      • 2018-11-02
      • 2020-04-15
      • 1970-01-01
      • 2012-09-15
      相关资源
      最近更新 更多