Skip to content
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

Amplify DataStore in React Native #4527

Closed
kennu opened this issue Dec 6, 2019 · 65 comments
Closed

Amplify DataStore in React Native #4527

kennu opened this issue Dec 6, 2019 · 65 comments
Labels
DataStore Related to DataStore category feature-request Request a new feature React Native React Native related issue

Comments

@kennu
Copy link

kennu commented Dec 6, 2019

I'm trying to use the new Amplify DataStore in React Native by adapting the instructions at https://aws.amazon.com/blogs/aws/amplify-datastore-simplify-development-of-offline-apps-with-graphql/ but I get a "Node is not supported" error.

Looking at this code:

const getDefaultAdapter: () => Adapter = () => {
it seems like IndexedDB is required, and I think it might not work in React Native.

Is there some special configuration or dependencies needed to make Amplify DataStore work in React Native?

@kennu kennu added the question General question label Dec 6, 2019
@sebsto
Copy link

sebsto commented Dec 6, 2019

https://twitter.com/undef_obj/status/1203072936237682689

React Naive bindings aren't published yet, need to get all the iOS and Android storage adapters fully published due to changes in the React Naive bridging system. Now that it's out we can get these bits published in the coming weeks then docs will get updated.

@efleurine
Copy link

Great I will be waiting too.

@elorzafe elorzafe added feature-request Request a new feature and removed question General question labels Dec 12, 2019
@cekali
Copy link

cekali commented Jan 2, 2020

Is there any update on this? A timeline, or a workaround would be great. Especially since it was announced as being compatible with React Native: https://aws.amazon.com/about-aws/whats-new/2019/12/introducing-amplify-datastore/

@sacrampton
Copy link

The advice of coming weeks was 27 days ago so hopefully not far away.

@OElesin
Copy link

OElesin commented Jan 11, 2020

Any updates on this yet and when shall we be expecting?

@davidbiller
Copy link

Curious about expo compatibility than

@grant-d
Copy link

grant-d commented Jan 28, 2020

From the twitter link in the issue immediately above, it looks like there is finally some movement:

We got a working prototype this past week and are looking to see if we can get it release ready in the next week or so.

@sammartinez
Copy link
Contributor

Update everyone, we believe we have a path forward for a release soon. Will reply when we have an ETA

@mwa3aan
Copy link

mwa3aan commented Feb 11, 2020

is there any update on the availability of these components? We have projects depending on it and it would really help to know if we should wait for this or use google firebase.

@sampsonjoliver
Copy link

Again from the twitter link, it looks like work is nearing completion bar for a few issues, and will be communicated here shortly.

Very excited for this, and thanks to everyone working on it :)

@Ashish-Nanda
Copy link
Contributor

Ashish-Nanda commented Feb 13, 2020

Amplify DataStore React Native Pre-Release

Hi All,

Today we published a pre-release of Amplify DataStore on React Native with a storage adapter that uses AsyncStorage underneath.
Please follow the instructions below to set up and test your App.

Setup the App

1) Create the app:

npx react-native init DatastoreApp
cd DataStoreApp

2) Install amplify related dependencies:

npm install -E @aws-amplify/core@rn-datastore @aws-amplify/datastore@rn-datastore 

3) Install and Link NetInfo:
For step 3, there are different instructions for Expo apps vs React Native CLI based apps. Follow the steps that are relevant for your setup:

  • For Expo Managed Apps:
    Install NetInfo with expo
expo install @react-native-community/netinfo

Thats all for Expo managed apps. Move directly to step 4)

  • For Apps created with React Native CLI:
    Install NetInfo through npm
npm install @react-native-community/netinfo

If using React Native > 0.60, run the following for iOS.

cd ios && pod install && cd ..

If you are using React Native <0.60 and need to link manually, refer to the react-native-community/netinfo getting started guide

4) Add Amplify DataStore to the app:
From the root directory of your app, run the following:

npx amplify-app@latest

5) Update the the schema:
After this completes, you can update the default GraphQL schema by modifying the following file:
amplify/backend/api/amplifyDatasource/schema.graphql

For this example we are going to use the following schema:

enum PostStatus {
  ACTIVE
  INACTIVE
}

type Post @model {
  id: ID!
  title: String!
  comments: [Comment] @connection(name: "PostComments")
  rating: Int!
  status: PostStatus!
}

type Comment @model {
  id: ID!
  content: String
  post: Post @connection(name: "PostComments")
}

6) Run codegen for the schema:
After saving the file, run the following command to generate your models:

 npm run amplify-modelgen

7) Create your API and cloud resources:

npm run amplify-push

8) Modify your App.js file:
In order to follow along with this example, replace your existing App.js file with this code.

9) Run the app
Run on iOS: npx react-native run-ios
or
Run on Android: npx react-native run-android

Test some DataStore use-cases in the App

Navigate to the AppSync console for your API
Run the following command from the root directory of your App:

amplify console api

Select GraphQL and press enter:

❯ GraphQL 
  REST 

A new tab will open in your browser that takes you to your AppSync API

Add some GraphQL queries to test in the console
Open the Queries tab of the AppSync Console. It contains an in-browser tool for writing, validating, and testing GraphQL queries. Add the following snippets to the editor on the left:

query getComments{
  syncComments {
    items {
      _deleted
      id
      content
      post {
        id
      }
    }
  }
}

query getPosts {
  syncPosts {
    items {
      id
      _deleted
      title
    }
  }
}

mutation createPost { 
  createPost(input: {
    title: "Post from backend",
    rating: 5,
    status: ACTIVE
  }) {
    id
    title
    rating
    status
    _version
    _deleted
    _lastChangedAt
  }
  
}

To run one of the above queries/mutations press the play button, and select the query you want to run.

Test Save

In the simulator, click ‘Create One Post’:

  1. A post will show up on the UI
  2. In the AppSync console click ‘getPosts’ to verify the Post is created in the backend.

Test Save for the for the one-many case

In the simulator click ‘Create Post & Comments’ (Should create one post with 2 comments)

  1. Only the post will show up on the UI
    (Comments are not rendered on the UI but if you are running the debugger, then you will see all comments in console.log statements)
  2. In AppSync console click:
  • ‘getPosts’ to confirm that the Post is created in the backend.
  • ‘getComments’ to confirm that the comments are created in the backend.

Test Subscriptions

In the AppSync console click ‘createPost’:

  1. The post should show up on the simulator UI

Test Queries
Queries are run as soon as the App starts, as well as whenever there is an update from a subscription. If you see data updated on the UI, the queries are running correctly.

You can test further by modifying the conditions in the code to filter results such as by rating, etc.

Test Delete

In the simulator click ‘DeletePosts’:

  1. All the posts are deleted and disappear from the UI
  2. In AppSync console click:
  • ‘getPosts’ to confirm that all the Posts returned have "_deleted": true
  • ‘getComments’ to confirm that all the comments returned have "_deleted": true

Note: If you would like to see the data in AsyncStorage for debugging purposes, click on ‘Get Store’ in the Simulator and make sure you have the debugger open.

Some Known Issues

Since this is a pre-release, there are some known issues below that we will be working on before the final release.

  • Currently the reachability aspect (detecting online/offline status) does not work very reliably when the app is in the background or if we switch off the internet and come back online. Offline data will be persisted but the subscriptions do not work immediately. Sometimes it takes a while for the app to come online, or you need to kill the app. After that the data is synced to the backend.
    Also note, NetInfo does not work correctly on iOS Simulator: NetInfo.isConnected.addEventListener behaves incorrectly on simulator react-native-netinfo/react-native-netinfo#7

  • We get some warnings in android regarding setTimeout which is probably part of the pubsub piece.

  • Issues with Buffer: Can‘t find variable:Buffer  facebook/react-native#14796
    We can try adding buffer as a dependency/peer-dependency. Or currently users need to add the following line in their Apps:

global.Buffer = global.Buffer || require('buffer').Buffer

Thank you

Your testing will help us get the final build out sooner so please let us know your feedback. Thank you.

@danrivett
Copy link

Great news!

One quick question: Do the instructions work with a non-ejected Expo app, or is that currently not supported? If not, could you confirm if that use case is intended to be supported in the final release?

@Ashish-Nanda
Copy link
Contributor

@danrivett While we have not yet tested on Expo apps, in theory it should work since all the dependencies like AsyncStorage and NetInfo are a part of Expo and wont require you to eject.

Do give it a try and let us know if you face any issues. I will be trying it out as well this week.

@davidbiller
Copy link

@danrivett While we have not yet tested on Expo apps, in theory it should work since all the dependencies like AsyncStorage and NetInfo are a part of Expo and wont require you to eject.

Do give it a try and let us know if you face any issues. I will be trying it out as well this week.

I guess you use asyncStorage from community?
So we have to use asyncStorage from „react-native“ with Expo.

@CarlitosBeto
Copy link

@danrivett While we have not yet tested on Expo apps, in theory it should work since all the dependencies like AsyncStorage and NetInfo are a part of Expo and wont require you to eject.

Do give it a try and let us know if you face any issues. I will be trying it out as well this week.

I try in my app in expo but i have the issue [Unhandled promise rejection: Error: Node is not supported]

@grant-d
Copy link

grant-d commented Feb 13, 2020

Thanks all. iOS seems to work fine (except for subscriptions which per above seems to be expected)
Android does not work - I get a runtime error Cannot use t"__Schema" from another module or realm
I have tried recreating it a couple of times but can't get around this error, eg:

    "dependencies": {
        "@aws-amplify/core": "^2.2.5-rn-datastore.3",
        "@aws-amplify/datastore": "^1.0.7-rn-datastore.3",
        "@react-native-community/netinfo": "^5.5.0",
        "graphql": "^14.6.0",  <-- Install this explicitly, using 14.0.0 and others
        "react": "16.9.0",
        "react-native": "0.61.5"
    },
    "resolutions": {
        "@aws-amplify/**/graphql": "^14.6.0" <-- No difference to error
    },

@edvinasbartkus
Copy link

I have a project using the web and react-native with the shared codebase. I tried to upgrade everything to rn-datastore.3 version and play with it. However, the web is working fine and is syncing data with the AppSync, but the iOS side can't retrieve objects. I constantly get an empty array [].
Is it supposed to be working with "authenticationType": "AMAZON_COGNITO_USER_POOLS"?

@gHashTag
Copy link

@Ashish-Nanda
What about the fact that Async Storage has a limit of 6MB.
facebook/react-native#7869
Is it planned to be replaced, and if so, for what?

@edvinasbartkus
Copy link

edvinasbartkus commented Feb 14, 2020

@Ashish-Nanda
What about the fact that Async Storage has a limit of 6MB.
facebook/react-native#7869
Is it planned to be replaced, and if so, for what?

@gHashTag

The size limitation for AsyncStorage is only on Android that can also be address with some configuration: https://github.com/react-native-community/async-storage/blob/LEGACY/docs/advanced/IncreaseDbSize.md

Moreover, AFAIK it's being worked on AsyncStorage v2 that would allow to create custom solutions how AsyncStorage persists the data. I guess one of the option would be writing to files (as iOS does?) or something else that would be more flexible.

@dmytro-kupriianov
Copy link

dmytro-kupriianov commented Feb 14, 2020

I try to save data and got next error

      const post =  await DataStore.save(
          new Post({
            title: `My Test post`,
            rating: 10,
            status: PostStatus.ACTIVE
          })
      );

[InvalidStateError: Failed to execute 'objectStore' on 'IDBTransaction': The transaction has finished.]
Source https://github.com/dimonchik-com/TestDataStore

@Ashish-Nanda
Copy link
Contributor

Ashish-Nanda commented Feb 15, 2020

@dimonchik-com @CarlitosBeto Its seems like your app is not picking up the React Native specific files and instead using web specific code. I will try out the test app you linked to as well as an expo app and report back. In the meantime could you try to run the app again after deleting node modules, and resetting the packager cache?

@dabit3
Copy link
Contributor

dabit3 commented Feb 19, 2020

Update!: This now works for me on both Expo as well as Expo web

@Ashish-Nanda Have set this up on Expo as well and it does not seem to be actually saving the data / syncing to the back end, only locally.

When I save a new post, it saves and will query locally without throwing any error. I can't seem to get it to sync with the database at all though when creating new posts. Not sure if I am doing something wrong.

Here are my dependency versions for Amplify:

"@aws-amplify/core": "2.2.5-rn-datastore.3",
"@aws-amplify/datastore": "1.0.7-rn-datastore.3",

Here is my code

Schema:

type Post @model {
  id: ID!
  title: String!
  comments: [Comment] @connection(name: "PostComments")
}

type Comment @model {
  id: ID!
  content: String
  post: Post @connection(name: "PostComments")
}

JavaScript

import React, { useEffect, useState } from "react";
import { Button, Text, View, TextInput } from 'react-native';
global.Buffer = global.Buffer || require('buffer').Buffer

import Amplify from '@aws-amplify/core'
import { DataStore } from "@aws-amplify/datastore";
import { Post } from "./src/models";

import config from './aws-exports'
Amplify.configure(config)

function App() {
  const [form, updateForm] = useState({ title: '' })
  const [posts, updatePosts] = useState([])
  async function query() {
    const postData = await DataStore.query(Post);
    updatePosts(postData)
  }
  async function create() {
    if (!form.title) return
    const postData = { ...form }
    await DataStore.save(
      new Post(postData)
    );
    console.log('successfully created new post')
    updateForm({ title: '' })
    query()
  }
  useEffect(() => {
    query()
  }, []);

  return (
    <View>
      <View style={{marginTop: 200}}>
        <TextInput
          value={form.title}
          placeholder="title"
          style={input}
          onChangeText={val => updateForm({ ...form, 'title': val })}
        />
        <Button onPress={create} title="Create Post" />
      </View>
      {
        posts.map((post, index) => (
          <View key={index}>
            <Text>{post.title}</Text>
          </View>
        ))
      }
    </View>
  );
}

const input = {
  height: 50,
  backgroundColor: '#ddd',
  padding: 10,
  margin: 10
}

export default App;

Have tested both on Expo with iOS and Expo Web

@edvinasbartkus
Copy link

@dabit3 make sure you add @versioned annotation to models. If I remember correctly that was an important bit for me using API token to auth in AppSync. For Cognito User Pool, I had to add @auth annotation too.

@Ashish-Nanda
Copy link
Contributor

@dabit3 Thanks for testing. I'll try out your code and will report back.

@undefobj
Copy link
Contributor

@dabit3 make sure you add @versioned annotation to models. If I remember correctly that was an important bit for me using API token to auth in AppSync. For Cognito User Pool, I had to add @auth annotation too.

@edvinasbartkus the @versioned directive should not be used with DataStore. AppSync does this automatically behind the scenes now and in a more comprehensive manner.

@Ashish-Nanda
Copy link
Contributor

Hi All,

We published a new version of React Native DataStore to the @rn-datastore tag that has fixes for some of the known issues.
Go ahead and install the new version as follows to test out the fixes:

npm install -E @aws-amplify/core@rn-datastore @aws-amplify/datastore@rn-datastore 

Here are some more details of the fixes that went into this release:

  1. We have fixed the dependency issues with buffer and you can now remove the following line from your app:
global.Buffer = global.Buffer || require('buffer').Buffer
  1. We have fixed the issue related to subscriptions failing when you come online. Now if you go offline and then come back online, subscriptions will work, without you needing to kill the app. You can test this on the Android Emulator or on iOS and Android Devices. It may not be possible to test this on iOS simulator due to the following issues with NetInfo: NetInfo.isConnected.addEventListener behaves incorrectly on simulator react-native-netinfo/react-native-netinfo#7

  2. If you lose connectivity to the network you should no longer get a red screen with the error:
    undefined is not an object (evaluating 'this._log.apply')

@edvinasbartkus
Copy link

@Ashish-Nanda thanks for the new version!

I tried to update, but now I do get the following warning on react-native and on the web:

WARN  [WARN] 02:48.579 DataStore - Sync error subscription failed Connection failed: {"errors":[{"message":"Validation error of type MissingFieldArgument: Missing field argument owner @ 'onCreateTrip'"}]}

Do I need to do any other updates?

@elorzafe
Copy link
Contributor

@edvinasbartkus did you make any change on the schema? Can you share your schema so we can reproduce? Thanks!

@elorzafe
Copy link
Contributor

@edvinasbartkus is your user logged in?

@CarlitosBeto
Copy link

@davidbiller @danrivett @CarlitosBeto

I tested React Native DataStore on an Expo managed app for both iOS and Android, and it works as expected.

The only difference in instructions is the NetInfo installation and linking step. I have updated the instructions in the original comment to include the steps specific to Expo. Feel free to give it a try and let us know your feedback.

thank you @Ashish-Nanda i review the installation and now the project compile, but i force the installation of package with command --save-exact i don´t know the reason but this fix the error.
And now i have other issue:
DataStore - Sync error, subscription failed Connection failed: {"errors":[{"message":"Validation error of type FieldUndefined: Field '_version'
And I couldn't query

@edvinasbartkus
Copy link

edvinasbartkus commented Feb 26, 2020

@elorzafe no changes for the schema, it was working well with *-rn-datastore.3
I use amazon cognito user identities and the user is logged in.

Here is the schema:

type Trip @model @versioned @auth(rules: [{ allow: owner }]) {
  id: ID!
  name: String!
  places: [Place] @connection(name: "TripPlaces")
}
type Place @model @versioned @auth(rules: [{ allow: owner }]) {
  id: ID!
  title: String!
  method: String
  lng: Float
  lat: Float
  trip: Trip @connection(name: "TripPlaces")
  comments: [Comment] @connection(name: "PlaceComments")
}
type Comment @model @versioned @auth(rules: [{ allow: owner }]) {
  id: ID!
  content: String
  place: Place @connection(name: "PlaceComments")
}

@Ashish-Nanda
Copy link
Contributor

@CarlitosBeto can you share your app on Github, or your schema with us?

@CarlitosBeto
Copy link

@Ashish-Nanda sure, this is my schema:

type Employee
@model
@key(name: "ByEmail", fields: ["email"], queryField: "employeesByEmail") {
id: ID!
createdAt: AWSDateTime
UpdatedAt: AWSDateTime
firstName: String!
lastName: String
fullName: String
dateOfBirth: AWSDateTime
identification: String
email: AWSEmail!
tramite: [Tramite]
@connection(name: "EmployeeTramite", keyField: "inspectorId")
inspectorId: ID
team: Team! @connection(name: "TeamEmployee", keyField: "teamId") #! cambio para compilar mobile
teamId: ID #ID!
rol: Rol @connection(name: "RolEmployee", keyField: "rolId")
rolId: ID
teamMan: Team! @connection(name: "TeamManager", keyField: "teamIdMan") #! cambio para compilar mobile
teamIdMan: ID #ID!
company: Company
@connection(name: "CompanyEmployee", keyField: "companyIdEmp")
companyIdEmp: ID
login: [Login] @connection(name: "EmpleadoLogin")
image: String
cambioEstado: CambioEstado @connection(name: "CambioEstadoEmpleado")
}

type Team @model {
id: ID!
name: String!
employees: [Employee] @connection(name: "TeamEmployee", keyField: "teamId")
teamId: ID
manager: Employee @connection(name: "TeamManager", keyField: "teamIdMan")
teamIdMan: ID!
tramite: [Tramite] @connection(name: "TeamTramite", keyField: "teamId")
}

type Channel @model {
id: ID!
firstName: String!
lastName: String
dateOfBirth: AWSDateTime
email: AWSEmail
}

type Company @model {
id: ID!
name: String!
address: String
logo: String
employees: [Employee]
@connection(name: "CompanyEmployee", keyField: "companyIdEmp")
companyIdEmp: ID
tramite: [Tramite] @connection(name: "CompanyTramite", keyField: "companyId")
companyId: ID
#grupo: Grupo @connection(name: "CompanyGrupo")
}

type Rol @model {
id: ID!
name: String!
empleado: [Employee] @connection(name: "RolEmployee", keyField: "rolId")
products: [Product] @connection(name: "RolProduct", keyField: "rolId")
}

type Product
@model
@key(name: "ByRolId", fields: ["rolId"], queryField: "productByRolId") {
id: ID!
name: String!
menu: AWSJSON
rol: Rol @connection(name: "RolProduct", keyField: "rolId")
rolId: ID
}

type Tramite
@model
@key(
name: "tramiteInspector"
fields: ["inspectorId"]
queryField: "tramiteInspector"
)
@key(
name: "tramiteTipoNum"
fields: ["tipo", "numTramite"]
queryField: "tramiteTipoNum"
) {
#@searchable
id: ID!
createdAt: AWSDateTime
numTramite: String!
oficialNegocio: String
nombreApellido: String
cedula: String
direccion: String
telefonos: String
tipoNegocio: String
destinoCredito: String
afct: String
monto: String
nombreApellido_IN: String
cedula_IN: String
direccion_IN: String
telefonos_IN: String
tipoNegocio_IN: String
destinoCredito_IN: String
afct_IN: String
monto_IN: String
direccionInversion: String
ruralUrbano: String
extension: String
esPropio: Boolean
esGravamen: Boolean
propietario: String
coorUTMZ: String
coorUTML: String
coorUTME: String
coorUTMN: String
uPLat: Float
uPLon: Float
descripcion: String
inventario: String
otrosActivos: String
observaciones: String
nombreApellidosGarante: String
cedulaGarante: String
direccionGarante: String
direccionHipoteca: String
telefonoGarante: String
nombreApellidosGarante_IN: String
cedulaGarante_IN: String
direccionGarante_IN: String
direccionHipoteca_IN: String
telefonoGarante_IN: String
inspector: Employee
@connection(name: "EmployeeTramite", keyField: "inspectorId")
inspectorId: ID
estado: TramiteEstado!
canton: String
provincia: String
agencia: String
regional: RegionalTramite
tipo: TipoTramite!
company: Company @connection(name: "CompanyTramite", keyField: "companyId")
companyId: ID
team: Team @connection(name: "TeamTramite", keyField: "teamId")
teamId: ID
cambioEstado: CambioEstado
@connection(name: "CambioEstadoTramite", keyField: "tramiteId")
observacion: String
grupo: Grupo @connection(name: "GrupoTramite", keyField: "grupoId")
grupoId: ID
imagen: [String]
fechaInspeccion: AWSDateTime
tipoProyecto: String
tipoPropiedad: String
parroquia: String
referencias: String
barrio: String
linderoNorte: String
linderoSur: String
linderoEste: String
linderoOeste: String
edificaciones: String
terreno: String
localComercial: String
infraestructuras: String
riesgosPotenciales: String
inventarioComercial: String
vivienda: String
herramientas: String
terrenos: String
unidadesProductivas: String
vehiculos: String
ingresosDemostrables: String
maquinarias: String
tipoGarantia: String
actEconPer: String
edificacionesHip: String
terrenoHip: String
extHip: String
localComercialHip: String
riesgosPotHip: String
observacionesHip: String
descripcionOtros: String
provinciaUbi: String
direccionUbi: String
cantonUbi: String
parroquiaUbi: String
referenciasUbi: String
barrioUbi: String
coorUTMZUbi: String
coorUTMLUbi: String
coorUTMEUbi: String
coorUTMNUbi: String
linderoNorteUbi: String
linderoSurUbi: String
linderoEsteUbi: String
linderoOesteUbi: String
firmaCliente: String
firmaGarante: String
}

type Login @model {
id: ID!
empleado: Employee @connection(name: "EmpleadoLogin")
fecha: AWSTimestamp
coords: AWSJSON
}

enum RegionalTramite {
IBARRA
QUITO
RIOBAMBA
PORTOVIEJO
GUAYAQUIL
CUENCA
LOJA
}

enum TipoTramite {
INSPECCION
REINSPECCION
VERIFICACION
}

enum TramiteEstado {
CARGADO #SUBE INF AL SISTEMA
AGENDADO #EQUIPO O PROP
REAGENDADO #EQUIPO O PROP /PRIORIDAD UNO
INSPECCION #EN INSPECCIÓN
PROCESANDO #AUN TRABAJO
FINALIZADO #TRABAJO INSP TERMINADO
VALIDANDO #TRABAJO VALIDADOR
CERRADO #LISTO PARA CLIENTE
}

type CambioEstado @model {
id: ID!
createdAt: AWSDateTime
estadoInicial: TramiteEstado
estadoFinal: TramiteEstado
tramite: [Tramite]
@connection(name: "CambioEstadoTramite", keyField: "tramiteId")
tramiteId: ID
usuario: Employee! #! cambio para compilar mobile
@connection(name: "CambioEstadoEmpleado", keyField: "employeeId")
employeeId: ID! #compila mobile
}

type Grupo @model {
id: ID!
createdAt: AWSDateTime
#company: Company @connection(name: "CompanyGrupo")
companyId: ID
nombre: String
tramite: [Tramite] @connection(name: "GrupoTramite", keyField: "grupoId")
grupoId: ID
fechaAsignacion: AWSDateTime
}

type Embarcacion @model {
id: ID!
createdAt: AWSDateTime
nombre: String
contactoPrincipal: String
tramite: String
ci_ruc: String
estadoCallCenter: String
observacion: String
representanteLegal: String
ceduladeIdentidadRL: String
apellidosRL: String
nombresRL: String
provincia: String
canton: String
parroquia: String
telefonoConvencional: String
telefonoMovil: String
correoElectronico: String
nombreEmbarcacion: String
matricula: String
puertoRegistro: String
tipodeNave: String
material: String
esloraTotal: String
esloraConvenio: String
manga: String
puntal: String
calado: String
tonelajeBruto: String
tonelajeNeto: String
valorEmbarcacion: String
totalMotor: String
totalAccesorios: String
totalArtes: String
avaluo: String
fechaAvaluo: String
ValorEmbarcacion: String
Serviciopesca: String
FechaConstruccion: String
FechaRegistro: String
TipoCasco: String
Propulsion: String
TipoCombustible: String
Motor1: String
Tipo1: String
Marca1: String
Modelo1: String
Potencia1: String
Troquelado1: String
Motor2: String
Tipo: String
Marca: String
Modelo: String
Potencia: String
Troquelado: String
GPS: String
Brujula: String
Ecosonda: String
Radio: String
Celular: String
Otros: String
EquiposAuxilio: String
ChalecosSalvavidas: String
LucesBengala: String
Boyasflotadores: String
}

maybe any command like --save-exact or force push into schema in cloud, because i belive this is not refresh

@Ashish-Nanda
Copy link
Contributor

@edvinasbartkus if you switch back to @rn-datastore.3 does it work again? It does not seem like the error you are getting is related to the changes in the datastore client, but we can use that to test if it's a regression.

@Ashish-Nanda
Copy link
Contributor

@CarlitosBeto its possible you have not pushed up your schema changes to AppSync since it is different from your comment here where you had @versioned in your schema.

Can you run the following:

  1. Run codegen:
npm run amplify-modelgen
  1. Push your changes to the backend:
npm run amplify-push
  1. Refresh your app

@CarlitosBeto
Copy link

@Ashish-Nanda, I remove @versioned and refresh but I have the same issue, the change is not work for me.
I though the version is failed but the version of diferents package is ok.
I saw the API file generate in app and the API have fields:
_version
_deleted
_lastChangedAt
version
And remove this fields and app running, therefore i supposed the error is in cloud version for the query.

@Ashish-Nanda
Copy link
Contributor

Ashish-Nanda commented Feb 26, 2020

@CarlitosBeto you should not be manually removing _version, _deleted, _lastChangedAt from any files.
I suggest we try the following. You are using Expo correct?
I can put up a simple expo app with a basic schema and instructions for you to test if queries, mutations and subscriptions work. You can try that and after confirming it works, you can modify it to see if you can get it working with your schema.

Would that be a good next step to help you out?

@manueliglesias
Copy link
Contributor

HI @CarlitosBeto can you DM me on twitter?
https://twitter.com/menyao

@CarlitosBeto
Copy link

Sure I sent a DM from CarlosBetoQ

@paddlefish
Copy link

Here are some tips as I worked through trying to get Auth to work with react-native:

You'll need to run amplify add auth: Here are the answers I used

Using service: Cognito, provided by: awscloudformation
The current configured provider is Amazon Cognito.
Do you want to use the default authentication and security configuration? Manual configuration
Select the authentication/authorization services that you want to use: I want to learn more.
Amazon Cognito identity pools provide temporary AWS credentials for users who are guests (unauthenticated) and for users who have been authenticated and received a token. An identity pool is a store of user identity data specific to your account.
If you choose to use the default configuration, this utility will set up both a Userpool and an Identity Pool.
Select the authentication/authorization services that you want to use: User Sign-Up, Sign-In, connected with AWS IAM controls (Enables per-user Storage features for images or other content, Analytics, and more)
Please provide a friendly name for your resource that will be used to label this category in the project: abrdatstob
Please enter a name for your identity pool. abrdatstob
Allow unauthenticated logins? (Provides scoped down permissions that you can control via AWS IAM) Yes
Do you want to enable 3rd party authentication providers in your identity pool? No
Please provide a name for your user pool: abrdatstob
Warning: you will not be able to edit these selections.
How do you want users to be able to sign in? Email
Do you want to add User Pool Groups? No
Do you want to add an admin queries API? No
Multifactor authentication (MFA) user login options: OFF
Email based user registration/forgot password: Enabled (Requires per-user email entry at registration)
Please specify an email verification subject: Your verification code
Please specify an email verification message: Your verification code is {####}
Do you want to override the default password policy for this User Pool? No
Warning: you will not be able to edit these selections.
What attributes are required for signing up? Email
Specify the app's refresh token expiration period (in days): 365
Do you want to specify the user attributes this app can read and write? No
Do you want to enable any of the following capabilities?
Do you want to use an OAuth flow? No
? Do you want to configure Lambda Triggers for Cognito? No
Successfully added resource abrdatstob locally
Some next steps:
"amplify push" will build all your local backend resources and provision it in the cloud
"amplify publish" will build all your local backend and frontend resources (if you have hosting categ

then amplify push to make those changes live. Make sure you use SHORT names for things, I've had cloud formation fail because the default proposed name ended up generating IAM role names that were too long. If that happens, do amplify remove auth, amplify push and try adding it again using a shorter name.

Any time after changing your schema.graphql file, e.g. to add an @auth(rules: [{ allow: owner }]) be sure to re run both amplify codegen model and also amplify push to update the schema.js and push those changes to AWS. You can confirm that auth was applied by looking in schema.js at the models.Posts.attributes which should have a new second entry "type": "auth", with other stuff in it. You can confirm that auth is setup in the cloud by logging into AppSync console, heading over to the tables in DynamoDB and you should see an owner column on the table.

Here's my schema

enum PostStatus {
  ACTIVE
  INACTIVE
}

type Post @model @auth(rules: [{ allow: owner }]) {
  id: ID!
  title: String!
  comments: [Comment] @connection(name: "PostComments")
  rating: Int!
  status: PostStatus!
}

type Comment @model @auth(rules: [{ allow: owner }]) {
  id: ID!
  content: String
  post: Post @connection(name: "PostComments")
}

After you add auth you need to delete all the rows from dynamodb. Because the old records won't have owner populated.

Also delete and re-add the app from your iOS simulator. That's because datastore on the simulator will have a cached copy of those deleted records -- which won't have owner properly set either.

Also, you will now need to add Auth to App.js. Here's my App.js based on the javascript sample for DataStore.

global.Buffer = global.Buffer || require('buffer').Buffer

import React, { useEffect, useState } from "react";

import Amplify from "@aws-amplify/core";
import { Authenticator } from 'aws-amplify-react-native';
import { DataStore, Predicates } from "@aws-amplify/datastore";

import { Post, PostStatus } from "./models";

import awsConfig from "../aws-exports";
import { Button, View, Text, ScrollView } from "react-native";
Amplify.configure(awsConfig);

function onCreate() {
  DataStore.save(
    new Post({
      title: `New title ${Date.now()}`,
      rating: (function getRandomInt(min, max) {
        min = Math.ceil(min);
        max = Math.floor(max);
        return Math.floor(Math.random() * (max - min)) + min; //The maximum is exclusive and the minimum is inclusive
      })(1, 7),
      status: PostStatus.ACTIVE
    })
  );
}

function onDeleteAll() {
  DataStore.delete(Post, Predicates.ALL);
}

async function onQuery(setPosts) {
  const posts = await DataStore.query(Post, c => c.rating("gt", 4));
  setPosts(posts)
}

async function listPosts(setPosts) {
  const posts = await DataStore.query(Post, Predicates.ALL);
  setPosts(posts);
}

async function bumpRating(post) {
  const copy = await Post.copyOf(post, p => p.rating = p.rating + 1);
  await DataStore.save(copy);
}

const SignedIn = (p) => {
  const [posts, setPosts] = useState([]);

  useEffect( () => {
    if (p.authState === 'signedIn') {
      listPosts(setPosts);

      const subscription = DataStore.observe(Post).subscribe(msg => {
        console.log(msg.model, msg.opType, msg.element);
        listPosts(setPosts);
      });

      // const handleConnectionChange = () => {
      //   const condition = navigator.onLine ? 'online' : 'offline';
      //   console.log(condition);
      //   if (condition === 'online') { listPosts(setPosts); }
      // }
      
      // window.addEventListener('online', handleConnectionChange);
      // window.addEventListener('offline', handleConnectionChange);
        
      return () => subscription.unsubscribe();
    } else {
      DataStore.clear()
    }
  }, [p.authState])

  if (p.authState !== 'signedIn') {
    return null
  }

  return (
    <View style={{margin: 20}}>
      <View>
        <Button title="NEW" onPress={() => { onCreate(); listPosts(setPosts)} } />
        <Button title="DELETE ALL" onPress={() => { onDeleteAll(); listPosts(setPosts)} } />
        <Button title="QUERY rating > 4" onPress={() => { onQuery(setPosts)} } />
        <Button title="ALL POST" onPress={() => { listPosts(setPosts)} } />
      </View>
      <ScrollView>
          {posts.map( (item,i) => {
            return <View key={i}>
              <Text>id: {posts[i].id.substring(0,8)}</Text>
              <Text>title: {posts[i].title}</Text>
              <Text>rating: {posts[i].rating}</Text>
              <Text>_version: {posts[i]._version}</Text>
              <Button title="Increase Rating" onPress={() => bumpRating(posts[i])}/>
            </View>
          } )}
      </ScrollView>
    </View>
  )
}

function App() {
  return (
    <Authenticator>
      <SignedIn />
    </Authenticator>
  );
}

export default App;

@Ashish-Nanda
Copy link
Contributor

@paddlefish thanks for your detailed example. Glad you were able to get it working.

@Ashish-Nanda
Copy link
Contributor

Amplify DataStore for React Native is now released

Hi All
We just released Amplify DataStore for React Native to @latest.
You can now simply do:

npm i @aws-amplify/core @aws-amplify/datastore

Please give it a try. You can find the updated Docs here: https://aws-amplify.github.io/docs/js/datastore

Thank you for helping us test the pre-release versions and we look forward to your feedback.

@Ashish-Nanda
Copy link
Contributor

Closing this feature request now that the feature has been delivered.

@jackatgh
Copy link

jackatgh commented Mar 3, 2020

For expo users
Just commenting here in case that people are running on the same issue.

@aws-amplify/datastore requires expo 36 since react-native-netinfo >= 4.x.x requires react native >= 0.60

@Ashish-Nanda maybe worth to mention on the official docs?

@subhendukundu
Copy link

Can I observe for a particular keyId? What I mean, is it possible to filter the data on observe?
Something link onCreateComment(postId: ID!)?

@dabit3
Copy link
Contributor

dabit3 commented Apr 21, 2020

@subhendukundu Yes, check out the docs here

@MaximeCamille
Copy link

MaximeCamille commented May 11, 2020

Does DataStore work for an AppSync API whos main data source is a lambda connecting to a AWS Neptune cluster? All the documentation seems to assume you're using DynamoDB and it seems the offline features (conflict resolution and delta sync) are only really suited for DynamoDB. I wanted to use DataStore for offline requirements because using the default AppSync method with Apollo Client seems to have issues since the release of Apollo 3.x.

@github-actions
Copy link

This issue has been automatically locked since there hasn't been any recent activity after it was closed. Please open a new issue for related bugs.

Looking for a help forum? We recommend joining the Amplify Community Discord server *-help channels or Discussions for those types of questions.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 11, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
DataStore Related to DataStore category feature-request Request a new feature React Native React Native related issue
Projects
None yet
Development

No branches or pull requests