aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.42k stars 2.12k forks source link

Error: Field should be of type string[], object received. null #6965

Closed hmisonne closed 3 years ago

hmisonne commented 3 years ago

I just want to mention that this is my first time trying to report a bug :bowtie:. I came across this issue while working on a React Native app with AWS amplify :rocket:!

I would appreciate any feedback :pray:.

Describe the bug

A GraphQL schema model with an optional string field (without exclamation mark) will throw an error if its content is null even:

datastore.js:222 Uncaught (in promise) Error: Field userGroceryListID should be of type string[], object received. null

To Reproduce Steps to reproduce the behavior:

  1. Create an AWS amplify react native app by following this tutorial

  2. Create a model in schema.graphql file

    type User @model {
    id: ID!
    name: String
    userGroceryListID: [String]
    }
  3. Update the API and database : amplify update api

  4. Add a DataStore by following this tutorial

  5. Update the App.js file with the following code:

import React, {  useEffect} from 'react'
import Amplify from 'aws-amplify'
import config from './aws-exports'
import { Auth } from 'aws-amplify'
import { DataStore } from "@aws-amplify/datastore";
import { User } from '../src/models'
import { withAuthenticator } from 'aws-amplify-react-native'

Amplify.configure({...config,
  Analytics: { 
    disabled: true
  }
})

const App = () => {
    useEffect(() => {
        identifyUser();
        const subscription = DataStore.observe(User).subscribe(msg => {
            console.log(msg.model, msg.opType, msg.element);
            identifyUser();
        })
        return () => subscription.unsubscribe();
    }, [])

    async function identifyUser() {
        try {
            const userInfo = await Auth.currentUserInfo()
            let users = await DataStore.query(User);
            let currUser
            if (users.length === 0){
                currUser = await DataStore.save(
                    new User({
                        id: userInfo.attributes.sub,
                        name: userInfo.username,
                        email: userInfo.attributes.email,
                    })
                  )
            } else {
                currUser = users[0]
            }

            dispatch(authentificateUser(currUser))
            console.log("User info retrieved successfully!");
        } catch (error) {
            console.log("Error retrieving user info", error);
        }

    };

}

export default withAuthenticator(App)
  1. Install all the dependencies and run the app from the root of your project:
npm install
npm run start
  1. Run the app in you browser and see the error: image

Expected behavior The application should run without errors

Code Snippet Here is the link to my repository

Config After running npx envinfo --system --binaries --browsers --npmPackages --npmGlobalPackages

 System:
    OS: Windows 10 10.0.18362
    CPU: (8) x64 Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz
    Memory: 6.05 GB / 15.78 GB
  Binaries:
    Node: 12.16.2 - C:\Program Files\nodejs\node.EXE
    npm: 6.14.4 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Chrome: 86.0.4240.75
    Edge: Spartan (44.18362.449.0)
    Internet Explorer: 11.0.18362.1
  npmPackages:
    @babel/core: ~7.9.0 => 7.9.6
    @iconify/icons-mdi: ^1.0.142 => 1.0.142
    @iconify/react: ^1.1.3 => 1.1.3
    @react-native-community/masked-view: 0.1.10 => 0.1.10
    @react-native-community/netinfo: ^5.9.7 => 5.9.7
    @react-native-community/picker: ^1.8.0 => 1.8.0
    @react-navigation/bottom-tabs: ^5.9.1 => 5.9.1
    @react-navigation/native: ^5.7.5 => 5.7.5
    @react-navigation/stack: ^5.9.2 => 5.9.2
    aws-amplify: ^3.3.2 => 3.3.2
    aws-amplify-react-native: ^4.2.7 => 4.2.7
    babel-plugin-transform-runtime: ^6.23.0 => 6.23.0
    babel-runtime: ^6.26.0 => 6.26.0
    expo: ~39.0.2 => 39.0.3
    expo-font: ^8.3.0 => 8.3.0
    expo-splash-screen: ^0.6.2 => 0.6.2
    expo-status-bar: ~1.0.2 => 1.0.2
    ini: ^1.3.5 => 1.3.5
    inquirer: ^6.5.1 => 6.5.2
    jest: ^26.4.2 => 26.4.2
    react: 16.13.1 => 16.13.1
    react-dom: 16.13.1 => 16.13.1
    react-native: https://github.com/expo/react-native/archive/sdk-39.0.2.tar.gz => 0.63.2
    react-native-gesture-handler: ~1.7.0 => 1.7.0
    react-native-reanimated: ~1.13.0 => 1.13.1
    react-native-safe-area-context: 3.1.4 => 3.1.4
    react-native-screens: ~2.10.1 => 2.10.1
    react-native-web: ~0.13.12 => 0.13.14
    react-redux: ^7.2.1 => 7.2.1
    react-test-renderer: ^16.13.1 => 16.13.1
    redux: ^4.0.5 => 4.0.5
  npmGlobalPackages:
    @aws-amplify/cli: 4.29.3
    @ionic/cli: 6.7.0
    bower: 1.8.8
    create-react-native-app: 3.1.0
    exp: 57.2.1
    expo-cli: 3.27.12
    express-generator: 4.16.1
    gulp: 4.0.2
    sequelize-cli: 6.1.0
    serverless: 1.71.3
    wscat: 4.0.0

Platform:

Suggestion to fix the issue

On the datastore file located here: C:\...\node_modules\@aws-amplify\datastore\lib-esm\datastore\datastore.js, I added the condition isRequired on the if statements on line 220 and 229.

wei commented 3 years ago

@hmisonne Thanks for the detailed issue description 👏 .

I started fresh and followed your reproduction steps and It's working just fine. I can create the new users with userGroceryListID: null and undefined both worked fine.

The working repo can be access at wei/amplify-js-6965

using macOS, latest amplify CLI 4.30.0 and latest node packages.
 npmPackages:
    @babel/core: ~7.9.0 => 7.9.6 
    @react-native-community/netinfo: ^5.9.7 => 5.9.7 
    aws-amplify: ^3.3.4 => 3.3.4 
    aws-amplify-react-native: ^4.2.7 => 4.2.7 
    expo: ~39.0.2 => 39.0.3 
    expo-status-bar: ~1.0.2 => 1.0.2 
    ini: ^1.3.5 => 1.3.5 
    inquirer: ^6.5.1 => 6.5.2 
    react: 16.13.1 => 16.13.1 
    react-dom: 16.13.1 => 16.13.1 
    react-native: https://github.com/expo/react-native/archive/sdk-39.0.3.tar.gz => 0.63.2 
    react-native-web: ~0.13.12 => 0.13.18 

Please let us know if this is still an issue you can reproduce from scratch. If so, please try to reproduce on top of my repo or create a fresh/minimal example repo using the latest CLI and packages. Thank you!

hmisonne commented 3 years ago

Thank you @wei it does work now. It looks like running the command amplify-modelgen is now generating : (string | null)[] for an optional field instead of just string[]

export declare class User {
  readonly id: string;
  readonly userGroceryListID?: (string | null)[];
  constructor(init: ModelInit<User>);
  static copyOf(source: User, mutator: (draft: MutableModel<User>) => MutableModel<User> | void): User;
}
wei commented 3 years ago

@hmisonne Amazing! Thanks for getting back to us with your success update! 🎉

github-actions[bot] commented 2 years ago

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.