Giter Site home page Giter Site logo

Comments (13)

NikaHsn avatar NikaHsn commented on June 10, 2024 1

Sorry that you are facing this issue and thanks for reporting it. We will look into this and get back to you when we have updates.

from amplify-flutter.

Equartey avatar Equartey commented on June 10, 2024 1

@filipesbragio thanks for the extra data point.

It appears iOS is dropping properties set to a null literal when making the request to AppSync. The work around would be to pass a non-null value to represent your type (if possible). If your property is a list, an empty list would also nullify the property. Same with an empty string.

We're currently investigating how to best resolve this and will update you as we can.

from amplify-flutter.

osehmathias avatar osehmathias commented on June 10, 2024

@NikaHsn - thanks, although I think it is a DataStore issue, not a GraphQL issue, as I experience this error with DataStore but not GraphQL.

from amplify-flutter.

Equartey avatar Equartey commented on June 10, 2024

Hi @osehmathias, I am unable to reproduce this.

.copyWithModelFieldValues() returns a new instance of the model which needs to be saved. This example works for me.

final entry = Entry(draftRecordID: 'foo');
print('Before: ${entry.draftRecordID}'); // Before: foo
final newEntry = entry.copyWithModelFieldValues(
    draftRecordID: const ModelFieldValue.value(null),
);
print('After: ${newEntry.draftRecordID}'); // After: null

Can you confirm how you are calling the copy method?


Also I noticed your schema Entry should have the @model decorator. I don't think this is causing issues, but it may have other side effects later on.

type Entry @model {
  id: ID!
  draftRecordID: ID @index
}

from amplify-flutter.

osehmathias avatar osehmathias commented on June 10, 2024

Hi @Equartey

I am calling the copy method like so:

final entry = Entry(draftRecordID: 'foo');
print('Before: ${entry.draftRecordID}'); // Before: foo
final newEntry = entry.copyWithModelFieldValues(
    draftRecordID: const ModelFieldValue.value(null),
);
print('After: ${newEntry.draftRecordID}'); // After: null
await Amplify.DataStore.save(newEntry);

// now fetch .... 

Entry fetchedEntry = await Amplify.DataStore.query(Entry.classType, where xxxx)
print('Fetched: ${fetchedEntry.draftRecordID}'); // Fetched entry, not cleared

Also I noticed your schema Entry should have the @model decorator. I don't think this is causing issues, but it may have other side effects later on.

Thank you. It does have the @model decorator. I edited it down when I posted the issue.

from amplify-flutter.

Equartey avatar Equartey commented on June 10, 2024

Hi @osehmathias

My apologies, I cannot reproduce this. I successfully nullified the property when saving before and after.

I tested on both iOS and Android with the same Flutter and Amplify versions. Here is my function & schema:

  Future<void> copyTest() async {
    final entry = Entry(draftRecordID: 'foo');
    print('Before: ${entry.draftRecordID}'); // Before: foo

    await Amplify.DataStore.save(entry);

    final resBefore = await Amplify.DataStore.query(Entry.classType,
        where: Entry.ID.eq(entry.id));
    print('resBefore: $resBefore'); // resBefore: Entry.draftRecordID = baz

    final newEntry = entry.copyWithModelFieldValues(
      draftRecordID: const ModelFieldValue.value(null),
    );
    print('After: ${newEntry.draftRecordID}'); // After: null

    await Amplify.DataStore.save(newEntry);

    final resAfter = await Amplify.DataStore.query(Entry.classType,
        where: Entry.ID.eq(entry.id));
    print('resAfter: ${resAfter}'); // resAfter: Entry.draftRecordID = null
  }
type Entry @model {
  id: ID!
  draftRecordID: ID @index
}

I'm not sure what could be the issue or different about our environments.

Can you confirm the ID's of the entries match?

Is there anything else specific with your setup that would help me reproduce the issue?

from amplify-flutter.

osehmathias avatar osehmathias commented on June 10, 2024

Hi @Equartey - I can see in the xcode logs that it sets it to null

"draftRecordID": Amplify.JSONValue.null,

However, when I refetch, the value is still there.

I have been able to get around this by setting the value of draftRecordID to '-' instead of null.

from amplify-flutter.

Equartey avatar Equartey commented on June 10, 2024

Hi @osehmathias. I looked into this again and could not reproduce. Your workaround is reasonable, but understandably not ideal.

Is the same behavior observed on Android?

Are you able to reproduce this on a fresh project?

from amplify-flutter.

osehmathias avatar osehmathias commented on June 10, 2024

Sorry about the delay, @Equartey.

This is how it's used.

      Entry updatedEntry = currentEntry.copyWithModelFieldValues(
          draftRecordID: const ModelFieldValue.value(null));
      await ref.read(entriesProvider.notifier).updateEntry(updatedEntry);

In this pattern, the provider updates the DB.

// provider.dart

final entriesProvider =
    StateNotifierProvider<EntriesProvider, List<Entry>?>((ref) {
  return EntriesProvider(ref);
});

class EntriesProvider extends StateNotifier<List<Entry>?> {
  Ref ref;
  EntriesProvider(this.ref) : super(null) {
    fetchEntries();
  }

  Future<void> updateEntry(Entry updatedEntry) async {
    try {
      await Amplify.DataStore.save(updatedEntry);
    } catch (e) {
      if (kDebugMode) {
        print('Error saving GoalEntry to DataStore: $e');
      }
      return;
    }
    if (state != null) {
      final index = state!.indexWhere((entry) => entry.id == updatedEntry.id);
      if (index != -1) {
        state = [
          for (int i = 0; i < state!.length; i++)
            if (i == index) updatedEntry else state![i]
        ];
      }
    }
  }
  }

For this reason, the state updates immediately and the mutation appears to be successful.

However, if I query the object afresh, such as when the app lifecycle changes, which in turn fetches data from the DataStore and updates the state ...

// main.dart

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    super.didChangeAppLifecycleState(state);
    if (state == AppLifecycleState.resumed) {
      var _ = ref.refresh(refreshAllProvider);
      initAuthController();
    }
  }

Or simply by making a call to Amplify.DataStore.query, or by querying on the AppSync API, or by looking in DynamoDB, I can see that the field has not been set to null and remains with its old value.

However, if I set the value to a string, it will update.

from amplify-flutter.

Equartey avatar Equartey commented on June 10, 2024

Hi @osehmathias, apologies for the delay.

I was able to reproduce this only on iOS, but not on Android. Are you seeing this issue on Android too?

Still digging into what the cause could be. We'll update you when we have more information to share.

from amplify-flutter.

osehmathias avatar osehmathias commented on June 10, 2024

Hi @Equartey

Thank you for the response. I have not tried to replicate this on Android yet, but as it happens, I am just about to develop the same app for Android so I will let you know once I have tested it and have that information.

from amplify-flutter.

Equartey avatar Equartey commented on June 10, 2024

@osehmathias, understood. Keep up posted. Thanks.

from amplify-flutter.

filipesbragio avatar filipesbragio commented on June 10, 2024

We seem to be having the same issue, except not on a basic type such as a string so the work around wouldn't work for us. It only happens with iOS, we haven't been able to reproduce it on android.

I suppose changing it to a list with only one value and then removing and re-adding to the list would solve it but I would very much like to avoid that.

from amplify-flutter.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.