aerogear / offix

GraphQL Offline Client and Server
https://offix.dev
Apache License 2.0
758 stars 45 forks source link

useOfflineMutation #449

Closed QuevedoIB closed 4 years ago

QuevedoIB commented 4 years ago

Hello and thanks for the library, I'm trying to achieve offline support using Apollo/GraphQL.

I've setup an implementation that looks like the React Native example but whenever I call useOfflineMutation inside my functional component I get the following error:

Screenshot 2020-05-11 at 13 14 29

My code:

import React, {useEffect, useState} from 'react';
import {
  View,
  Text,
  ActivityIndicator,
  FlatList,
  TouchableOpacity,
} from 'react-native';

import {FETCH_TODOS} from '../../graphql/queries/fetchTodos';
import {ADD_TODO} from '../../graphql/queries/addTodo';
import {TOGGLE_TODO} from '../../graphql/queries/toggleTodo';

import {useDarkModeContext} from '../../helpers/DarkMode/context';

import {useQuery} from '@apollo/react-hooks';
import {useOfflineMutation} from 'react-offix-hooks';
import {mutateOptions} from '../../helpers/mutateOptions';

import translations from '../../translations/config';

import styles from './styles';

const HomeScreen = ({navigation}) => {
  const {theme} = useDarkModeContext();
  const {data: remoteData, error, loading} = useQuery(FETCH_TODOS);

  const [addTodo] = useOfflineMutation(
    ADD_TODO,
    mutateOptions(FETCH_TODOS, 'todo', 'add'),
  );

  const [toggleTodo] = useOfflineMutation(
    TOGGLE_TODO,
    mutateOptions(FETCH_TODOS, 'todo', 'refresh'),
  );

  const onCompleteTodo = todoID => {
    toggleTodo({variables: {id: todoID}});
  };

  const renderTodos = ({item}) => {
    return (
      <View style={{marginVertical: 16}}>
        <Text style={{alignSelf: 'center'}}>Title: {item.title}</Text>
        <Text style={{alignSelf: 'center'}}>
          Completed: {item.completed ? 'TRUE' : 'FALSE'}
        </Text>
        {!item.completed && (
          <TouchableOpacity
            style={{alignSelf: 'center', marginVertical: 8}}
            onPress={() => onCompleteTodo(item.id)}>
            <Text>Complete</Text>
          </TouchableOpacity>
        )}
      </View>
    );
  };

  const renderList = () => {
    const {todos} = remoteData;

    return (
      <FlatList
        showsVerticalScrollIndicator={false}
        data={todos}
        renderItem={renderTodos}
        keyExtractor={({id}) => id}
      />
    );
  };

  return (
    <View style={{flex: 1, alignItems: 'center'}}>
      <Text style={styles[theme].title}>{translations.t('home.title')}</Text>
      {remoteData ? renderList() : <ActivityIndicator />}
    </View>
  );
};

export default HomeScreen;

App.js:

import 'react-native-gesture-handler';
import React, {useState, useEffect} from 'react';
import {StatusBar, ActivityIndicator} from 'react-native';
import {NavigationContainer, DefaultTheme} from '@react-navigation/native';
import {createStackNavigator} from '@react-navigation/stack';
import EStyleSheet from 'react-native-extended-stylesheet';

import {ApolloOfflineProvider} from 'react-offix-hooks';

import HomeScreen from './src/screens/HomeScreen';
import HeaderSwitchTheme from './src/components/ThemeSwitch';

import * as tokens from './src/style-dictionary-dist/variables';

import {
  DarkModeProvider,
  useDarkModeContext,
} from './src/helpers/DarkMode/context';
import {ApolloProvider} from 'react-apollo';
import apolloClientGenerator from './src/graphql/apollo';

const Stack = createStackNavigator();
EStyleSheet.build({});

export default function App() {
  //Change themes for dark mode

  const {theme, changeTheme} = useDarkModeContext();

  const [client, setClient] = useState(null);

  useEffect(() => {
    createApolloClient();
  }, []);

  const createApolloClient = async token => {
    const generatedClient = await apolloClientGenerator(token);
    await generatedClient.init();
    setClient(generatedClient);
  };

  const darkTheme = {
    ...DefaultTheme,
    dark: true,
    colors: {
      ...DefaultTheme.colors,
      primary: tokens.ColorFontInverseBase, //brand color
      background: tokens.ColorBackgroundInverse, //screen background
      card: tokens.ColorBaseGrey900, //header background
      border: tokens.ColorBaseGrey900, //header bottom border
      text: tokens.ColorBaseGrey50, //text color header
    },
  };

  const lightTheme = {
    ...DefaultTheme,
    dark: false,
    colors: {
      ...DefaultTheme.colors,
    },
  };

  const barTheme = {
    dark: 'light-content',
    light: 'dark-content',
  };

  if (!client) {
    return <ActivityIndicator />;
  }

  return (
    <ApolloOfflineProvider client={client}>
      <ApolloProvider client={client}>
        <DarkModeProvider mode={{theme}}>
          <StatusBar barStyle={barTheme[theme]} />
          <NavigationContainer
            theme={theme === 'light' ? lightTheme : darkTheme}>
            <Stack.Navigator>
              <Stack.Screen
                name="Home"
                component={HomeScreen}
                options={{
                  headerRight: () => (
                    <HeaderSwitchTheme
                      selected={theme}
                      onChange={changeTheme}
                    />
                  ),
                }}
              />
            </Stack.Navigator>
          </NavigationContainer>
        </DarkModeProvider>
      </ApolloProvider>
    </ApolloOfflineProvider>
  );
}

My package.json:

 "dependencies": {
    "@apollo/react-hooks": "^3.1.5",
    "@react-native-community/async-storage": "^1.10.0",
    "@react-native-community/masked-view": "^0.1.10",
    "@react-native-community/netinfo": "^5.8.0",
    "@react-navigation/native": "^5.1.7",
    "@react-navigation/stack": "^5.2.14",
    "@tradle/react-native-http": "^2.0.1",
    "apollo-cache-inmemory": "^1.6.5",
    "apollo-cache-persist": "^0.1.1",
    "apollo-client": "^2.6.8",
    "apollo-link": "^1.2.14",
    "apollo-link-http": "^1.5.17",
    "axios": "^0.19.2",
    "graphql": "^15.0.0",
    "graphql-tag": "^2.10.3",
    "i18n-js": "^3.5.1",
    "offix-cache": "^0.15.1",
    "offix-client": "^0.15.1",
    "react": "16.11.0",
    "react-apollo": "^3.1.5",
    "react-native": "0.62.2",
    "react-native-extended-stylesheet": "^0.12.0",
    "react-native-gesture-handler": "^1.6.1",
    "react-native-reanimated": "^1.8.0",
    "react-native-safe-area-context": "^0.7.3",
    "react-native-screens": "^2.7.0",
    "react-offix-hooks": "^0.15.1"
  }

Any help is highly appreciated.

QuevedoIB commented 4 years ago

Just cloned the repo and tested the react native example and it gives the same error:

Screenshot 2020-05-11 at 14 54 39

Steps to reproduce: Clone this repo: Go to the examples folder -> react native example npm i && cd ios && pod install open Xcode -> rnative.xcworkspace launch App

darahayes commented 4 years ago

Ping @kingsleyzissou you might have a quick answer for this one. Otherwise I should get a chance to look at it some time tomorrow!

wtrocki commented 4 years ago

It is strange as we haven't changed much and example app did work before. We will ensure we do proper testing for all of our example apps including react and react native in future releases.

What I can think of is that some of the package updates changed the way we wrap apollo hooks into class. @QuevedoIB we will be back to you as soon as possible with the fix.

Related code that causes problem: https://github.com/aerogear/offix/blob/7d8ea824708dce911f51e646c6f4e65fabd9a0ff/packages/react-offix-hooks/src/useOfflineMutation.ts#L74

kingsleyzissou commented 4 years ago

This is a strange one. The React-Native example is still working for me without that error.

Going to dig into it a little bit more today

KirioXX commented 4 years ago

Hi, we have the same issue after we upgraded to react-native 0.62.2. The recommended react version for 0.62 is v16.11.0, I upgraded the version to v16.13.1 and everything seems to work fine again.

wtrocki commented 4 years ago

@KirioXX Thank you so much for leaving this awesome comment. We will update the sample app to this version as well to give devs reference

dinhmai74 commented 4 years ago

Can you share package.json @KirioXX , I still have that issue 🙁

KirioXX commented 4 years ago

@dinhmai74 Sure

{
  "name": "mobile",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "android:demo": "ENVFILE=.env.demo react-native run-android --variant=DemoDebug --appIdSuffix=demo",
    "android:prod": "ENVFILE=.env react-native run-android --variant=ProdDebug",
    "android": "ENVFILE=.env.dev react-native run-android --variant=DevDebug --appIdSuffix=test",
    "codegen": "apollo client:codegen -c ./apollo.config.js --target=typescript --globalTypesFile=./App/types/globalTypesFile.ts",
    "ios:demo": "react-native run-ios --scheme \"PatchworkDemo\" --configuration Debug",
    "ios:prod": "react-native run-ios --scheme \"Patchwork\" --configuration Debug",
    "ios": "react-native run-ios --scheme \"PatchworkDev\" --configuration Debug",
    "start": "react-native start",
    "test": "jest -c ./jest.config.js"
  },
  "dependencies": {
    "@gigasz/react-native-sketch-canvas": "0.8.3",
    "@heap/react-native-heap": "0.10.0",
    "@patchwork/config": "1.0.0",
    "@patchwork/library": "1.0.0",
    "@patchwork/resources": "1.0.0",
    "@react-native-community/async-storage": "1.9.0",
    "@react-native-community/masked-view": "0.1.7",
    "@react-native-community/netinfo": "5.8.0",
    "@react-native-community/viewpager": "3.3.0",
    "@react-native-firebase/analytics": "6.4.0",
    "@react-native-firebase/app": "6.4.0",
    "@react-native-firebase/crashlytics": "6.4.0",
    "@react-native-firebase/dynamic-links": "6.4.0",
    "@react-native-firebase/messaging": "6.4.0",
    "@react-native-firebase/perf": "6.4.0",
    "@react-native-firebase/remote-config": "6.4.0",
    "@react-navigation/bottom-tabs": "5.2.6",
    "@react-navigation/native": "5.1.5",
    "@react-navigation/stack": "5.2.10",
    "apollo-cache-inmemory": "1.6.5",
    "apollo-cache-persist": "0.1.1",
    "apollo-client": "2.6.8",
    "apollo-link": "1.2.14",
    "apollo-link-context": "1.0.20",
    "apollo-link-error": "1.1.13",
    "apollo-link-http": "1.5.17",
    "apollo-link-retry": "2.2.16",
    "appcenter": "3.0.2",
    "babel-plugin-transform-remove-console": "6.9.4",
    "color": "3.1.2",
    "expo-document-picker": "8.1.0",
    "expo-file-system": "8.1.0",
    "formik": "2.1.4",
    "fuse.js": "5.1.0",
    "graphql": "15.0.0",
    "graphql-tag": "2.10.3",
    "jwt-decode": "2.2.0",
    "moment": "2.24.0",
    "moment-timezone": "0.5.28",
    "offix-client": "0.15.1",
    "react": "16.13.1",
    "react-apollo": "3.1.4",
    "react-native": "0.62.2",
    "react-native-add-calendar-event": "3.0.2",
    "react-native-calendars": "1.265.0",
    "react-native-config": "1.0.0",
    "react-native-device-info": "5.5.4",
    "react-native-easy-content-loader": "0.3.2",
    "react-native-email-link": "1.7.3",
    "react-native-fast-image": "8.1.5",
    "react-native-gesture-handler": "1.6.1",
    "react-native-image-picker": "2.3.1",
    "react-native-intercom": "14.0.0",
    "react-native-keyboard-aware-scroll-view": "0.9.1",
    "react-native-location": "2.5.0",
    "react-native-reanimated": "1.8.0",
    "react-native-safe-area-context": "0.7.3",
    "react-native-screens": "2.4.0",
    "react-native-share": "3.2.0",
    "react-native-splash-screen": "3.2.0",
    "react-native-svg": "12.1.0",
    "react-native-unimodules": "0.9.0",
    "react-native-version-number": "0.3.6",
    "react-offix-hooks": "0.15.1",
    "remove": "0.1.5",
    "rn-secure-storage": "2.0.4",
    "rollbar-react-native": "0.7.2",
    "url": "0.11.0",
    "waait": "1.0.5",
    "yup": "0.28.3"
  },
  "devDependencies": {
    "reactotron-react-native": "5.0.0"
  },
  "workspaces": {
    "nohoist": [
      "**"
    ]
  }
}
dinhmai74 commented 4 years ago

thank bro @KirioXX , It's work now 😍

QuevedoIB commented 4 years ago

Unluckily for me upgrading react to 16.13.1 didn't do the trick:

 "dependencies": {
    "@apollo/react-hooks": "^3.1.5",
    "@react-native-community/async-storage": "^1.10.0",
    "@react-native-community/masked-view": "^0.1.10",
    "@react-native-community/netinfo": "^5.8.0",
    "@react-navigation/native": "^5.1.7",
    "@react-navigation/stack": "^5.2.14",
    "@tradle/react-native-http": "^2.0.1",
    "apollo-cache-inmemory": "^1.6.5",
    "apollo-cache-persist": "^0.1.1",
    "apollo-client": "^2.6.8",
    "apollo-link": "^1.2.14",
    "apollo-link-http": "^1.5.17",
    "axios": "^0.19.2",
    "graphql": "^15.0.0",
    "graphql-tag": "^2.10.3",
    "i18n-js": "^3.5.1",
    "offix-cache": "^0.15.1",
    "offix-client": "^0.15.1",
    "react": "^16.13.1",
    "react-apollo": "^3.1.4",
    "react-native": "0.62.2",
    "react-native-extended-stylesheet": "^0.12.0",
    "react-native-gesture-handler": "^1.6.1",
    "react-native-get-random-values": "^1.4.0",
    "react-native-reanimated": "^1.8.0",
    "react-native-safe-area-context": "^0.7.3",
    "react-native-screens": "^2.7.0",
    "react-offix-hooks": "^0.15.1",
    "uuid": "^8.0.0"
  }

For now I'm using the mutation directly to the client instead of using the hook.

QuevedoIB commented 4 years ago

Guess my error comes from: npm ls react

Screenshot 2020-05-14 at 11 35 08
wtrocki commented 4 years ago

I quess we need to add react as peerDependency but with the wider qualifier. This should not cause any issue though as react will be there - this is more issue related to package failing check.

I have create PR to fix this: https://github.com/aerogear/offix/pull/459

kingsleyzissou commented 4 years ago

@QuevedoIB sorry for the delay on getting back to you on this. I have managed to reproduce the issue and I'm looking into it at the moment.

Can you please try removing the node_modules dir and the yarn.lock or package-lock.json and re-run yarn/npm install ?

Reason being is you'll have to reinstall the react-offix-hooks package, because initially the react peer dependancy had not been met. That's would explain why the npm ls react is listing another version of react in the react-offix hooks package. Hopefully his will resolve this for you.

kingsleyzissou commented 4 years ago

Closing this issue since we have not been able to reproduce this issue and have proposed a solution for how to fix this. If you are still having issues, please feel free to re-open.

philwilliammee commented 3 years ago

I had the same issue trying to run the example app changing package.json to:

    "react": "16.13.1",
    "react-dom": "16.13.1",

solved the issue for me