Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Undefined is not a function in expo app #3197

Closed
3 tasks done
elisalimli opened this issue Apr 29, 2023 · 2 comments
Closed
3 tasks done

Undefined is not a function in expo app #3197

elisalimli opened this issue Apr 29, 2023 · 2 comments
Labels
needs more info ✋ A question or report that needs more info to be addressable

Comments

@elisalimli
Copy link

elisalimli commented Apr 29, 2023

Describe the bug

Hi,

I am using Expo and urql as my graphql client.

When I try to write a simple screen to get hello query and print it to the screen the Undefined is not a function error occurs.

CODE :

import React from "react";
import { StyleSheet, Text, View } from "react-native";
import { use query, gql } from "urql";

const HELLO_QUERY = gql`
  query {
    hello
  }
`;

export default function HelloScreen() {
  const [{ data, fetching, error }] = useQuery({ query: HELLO_QUERY });

  if (fetching) {
    return <Text>Loading...</Text>;
  }

  if (error) {
    return <Text>Error: {error.message}</Text>;
  }

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Hello</Text>
      <Text style={styles.text}>{data.hello}</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: "center",
    justifyContent: "center",
    backgroundColor: "#fff",
  },
  title: {
    fontSize: 32,
    marginBottom: 16,
  },
  text: {
    fontSize: 24,
  },
});

I resolved this error by downgrading the Urql version from 4.0.2 to 3.0.4.

What causes this problem and how to solve it?

Urql version

urql v4.0.2

Validations

  • I can confirm that this is a bug report, and not a feature request, RFC, question, or discussion, for which GitHub Discussions should be used
  • Read the docs.
  • Follow our Code of Conduct
@kitten kitten added the needs more info ✋ A question or report that needs more info to be addressable label Apr 29, 2023
@kitten
Copy link
Member

kitten commented Apr 29, 2023

I'm going to he honest here, there's a high likelihood that you didn't check the migration guide for v4: #3114

There's likely one of two problems in your app:

  • You haven't created a client and provider
  • You haven't passed the default exchanges to your client

However, without a full error message with a stack trace or a full description, I can't really tell.

Just to point this out, we've got Discord GitHub Discussions to help with debugging and questions, because it's easier to have a back and forth there 👀

@elisalimli
Copy link
Author

I read the migration guide.

This is my client

import { getAuthAccessToken, saveAuthAccessToken } from "../auth/auth";
import { authExchange } from "@urql/exchange-auth";
import { refreshTokenMutationDocument } from "./mutation/user/refershToken";

export const client = createClient({
  url: "http://localhost:4000/query",
  fetchOptions: { credentials: "include" },
  exchanges: [
    cacheExchange,
    //@ts-ignore
    authExchange(async (utils) => {
      let token = await getAuthAccessToken();
      console.log("token", token);
      return {
        addAuthToOperation(operation) {
          if (!token) return operation;
          return utils.appendHeaders(operation, {
            Authorization: `Bearer ${token}`,
          });
        },

        didAuthError(error, _operation) {
          return error.graphQLErrors.some((e) => {
            console.log(
              "did auth error",
              e.extensions,
              e.extensions?.code === "FORBIDDEN"
            );
            return e.extensions?.code === "FORBIDDEN";
          });
        },
        async refreshAuth() {
          const result = await utils.mutate(refreshTokenMutationDocument, {});

          if (result.data?.refreshToken?.authToken) {
            // Update our local variables and write to our storage
            token = result.data.refreshToken.authToken!.token;
            saveAuthAccessToken(token);
          } else {
            // This is where auth has gone wrong and we need to clean up and redirect to a login page
            // localStorage.clear();
            // logout();
          }
        },
      };
    }),
    fetchExchange,
  ],
});

And I'm passing the client to my Provider:

import FontAwesome from "@expo/vector-icons/FontAwesome";
import {
  DarkTheme,
  DefaultTheme,
  ThemeProvider,
} from "@react-navigation/native";
import { useFonts } from "expo-font";
import { SplashScreen, Stack } from "expo-router";
import React, { useEffect } from "react";
import { useColorScheme } from "react-native";
import { AuthProvider } from "../context/auth";

export { ErrorBoundary } from "expo-router";

import { Provider } from "urql";
import { client } from "../src/graphql/client";

export const unstable_settings = {
  // Ensure that reloading on `/modal` keeps a back button present.
  initialRouteName: "(tabs)",
};

export default function RootLayout() {
  const [loaded, error] = useFonts({
    SpaceMono: require("../assets/fonts/SpaceMono-Regular.ttf"),
    ...FontAwesome.font,
  });

  // Expo Router uses Error Boundaries to catch errors in the navigation tree.
  useEffect(() => {
    if (error) throw error;
  }, [error]);

  return (
    <>
      {/* Keep the splash screen open until the assets have loaded. In the future, we should just support async font loading with a native version of font-display. */}
      {!loaded && <SplashScreen />}
      {loaded && <RootLayoutNav />}
    </>
  );
}

function RootLayoutNav() {
  const colorScheme = useColorScheme();

  return (
    <>
      <ThemeProvider value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
        <Provider value={client}>
          <AuthProvider>
            <Stack>
              <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
              <Stack.Screen name="modal" options={{ presentation: "modal" }} />
            </Stack>
          </AuthProvider>
        </Provider>
      </ThemeProvider>
    </>
  );
}

@urql-graphql urql-graphql locked and limited conversation to collaborators Apr 30, 2023
@kitten kitten converted this issue into discussion #3203 Apr 30, 2023

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
needs more info ✋ A question or report that needs more info to be addressable
Projects
None yet
Development

No branches or pull requests

2 participants