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.43k stars 2.13k forks source link

[TypeError: Cannot read property 'create' of undefined] #13626

Closed Jinyoung3 closed 2 months ago

Jinyoung3 commented 3 months ago

Before opening, please confirm:

JavaScript Framework

React Native

Amplify APIs

GraphQL API

Amplify Version

v6

Amplify Categories

No response

Backend

Amplify Gen 2 (Preview)

Environment information

``` # Put output below this line ```

Describe the bug

import React, { useState } from "react";
import { View, Text, TextInput, Button, StyleSheet, ScrollView, Alert } from "react-native";
import { generateClient } from "aws-amplify/data";
import type { Schema } from "./amplify/data/resource";
import { StackNavigationProp } from '@react-navigation/stack';
import { RouteProp } from '@react-navigation/native';
import { RootStackParamList, ProfileType } from "./types";

type ProfileScreenNavigationProp = StackNavigationProp<
  RootStackParamList,
  'Profile'
>;

type ProfileScreenRouteProp = RouteProp<RootStackParamList, 'Profile'>;

type Props = {
  navigation: ProfileScreenNavigationProp;
  route: ProfileScreenRouteProp;
};
const client = generateClient<Schema>()
const ProfileScreen:React.FC<Props> = ({navigation}) => {
  const [username, setUsername] = useState('');
  const [personalRecord, setPersonalRecord] = useState('');

  const handleCreateProfile = async () => {
    if (!username.trim()) {
      Alert.alert('Validation Error', 'Username cannot be empty.');
      return;
    }
    if (!personalRecord.trim()) {
      Alert.alert('Validation Error', 'Personal Record cannot be empty.');
      return;
    }
    try {
      await client.models.Profile.create({
        username: username,
        personalRecord: personalRecord
      });
      navigation.navigate("WorkoutList");
    } catch (error) {
      console.log("Error creating profile:", error);
    }
  };

  return (
    <View style={styles.container}>
      <Text style={styles.label}>Username</Text>
      <TextInput
        style={styles.input}
        value={username}
        onChangeText={setUsername}
      />
      <Text style={styles.label}>Personal Record</Text>
      <TextInput
        style={styles.input}
        value={personalRecord}
        onChangeText={setPersonalRecord}
      />
      <Button title="Create Profile" onPress={handleCreateProfile} />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 16,
  },
  label: {
    marginBottom: 4,
  },
  input: {
    borderWidth: 1,
    borderColor: '#ccc',
    padding: 8,
    marginBottom: 8,
  },
});

export default ProfileScreen;
When I click button the error shows up.

import type { Schema } from "./amplify/data/resource";

// Define a type for the required properties of a Workout
type WorkoutType = {
  name: string;
  exercises: string; // JSON string representing exercises
  createdAt: string;
  id: string;
};

// Define a type for a Set
interface Set {
  reps: string;
  weight: string;
}

// Update the Exercise type to include sets
interface Exercise {
  name: string;
  sets: Set[];
}

// Define a type for Profile
type ProfileType = {
  username: string | null;
  personalRecord: string | null;
};

export type RootStackParamList = {
  Home: undefined;
  WorkoutList: undefined;
  AddWorkout: undefined;
  WorkoutDetail: { workout: WorkoutType };
  Profile: undefined;
  EditProfile: { profile: ProfileType };
  CreatePost: undefined;
  TodoList: undefined;
};

export type { WorkoutType, Exercise, Set, ProfileType };(this is the type.ts)
import { type ClientSchema, a, defineData } from '@aws-amplify/backend';

const schema = a.schema({
  Todo: a
    .model({
      content: a.string(),
      isDone: a.boolean()
    })
    .authorization(allow => [allow.owner()]),
  Workout: a
    .model({
      name: a.string(),
      exercises: a.string(), // Storing as JSON string as per requirement
      createdAt: a.datetime()
    })
    .authorization(allow => [allow.owner()]),
  Post: a
    .model({
      id: a.string(),
      text: a.string(),
      imageKey: a.string(),
      createdAt: a.datetime(),
      updatedAt: a.datetime()
    })
    .authorization(allow => [allow.owner()]),
  Profile: a
    .model({
      username: a.string(),
      personalRecord: a.string()
    })
    .authorization(allow => [allow.owner()])
});

export type Schema = ClientSchema<typeof schema>;

export const data = defineData({
  schema,
  authorizationModes: {
    defaultAuthorizationMode: 'userPool'
  }
});(this is resource.ts)
type Todo @model @auth(rules: [{allow: public}]) {
  id: ID!
  name: String!
  description: String
}

type Profile @model @auth(rules: [{allow: owner}]) {
  username: String!
  personalRecord: String
} (this is my schema graph ql)
import { type ClientSchema, a, defineData } from '@aws-amplify/backend';

const schema = a.schema({
  Todo: a
    .model({
      content: a.string(),
      isDone: a.boolean()
    })
    .authorization(allow => [allow.owner()]),
  Workout: a
    .model({
      name: a.string(),
      exercises: a.string(), // Storing as JSON string as per requirement
      createdAt: a.datetime()
    })
    .authorization(allow => [allow.owner()]),
  Post: a
    .model({
      id: a.string(),
      text: a.string(),
      imageKey: a.string(),
      createdAt: a.datetime(),
      updatedAt: a.datetime()
    })
    .authorization(allow => [allow.owner()]),
  Profile: a
    .model({
      username: a.string(),
      personalRecord: a.string()
    })
    .authorization(allow => [allow.owner()])
});

export type Schema = ClientSchema<typeof schema>;

export const data = defineData({
  schema,
  authorizationModes: {
    defaultAuthorizationMode: 'userPool'
  }
});(this is my client.ts)

Expected behavior

I get error saying create is undefined. I printed out the textinputs but they are correct so I don't know what the issue is.

Reproduction steps

https://github.com/Jinyoung3/awsman.git this is my github depository you can just git clone that URL and the issue is from profile.tsx

Code Snippet

// Put your code below this line.

Log output

``` // Put your logs below this line ```

aws-exports.js

No response

Manual configuration

No response

Additional configuration

No response

Mobile Device

No response

Mobile Operating System

No response

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

No response

chrisbonifacio commented 3 months ago

Hi @Jinyoung3 👋 Thank you for raising this issue!

Did you mean to share the schema twice? It seems like you might have the schema defined in two separate files, once in the data/resource.ts file and again in a type.ts file?

In any case, it isn't clear if you have called Amplify.configure(). That has to be called before generateClient for client.models.* to be defined and type complete.

Can you make sure that you are configuring Amplify somewhere higher in the component tree? Ideally at the earliest point the app renders, typically in an entry point file such as App.tsx.

chrisbonifacio commented 2 months ago

Hi 👋 Closing this as we have not heard back from you. If you are still experiencing this issue and in need of assistance, please feel free to comment and provide us with any information previously requested by our team members so we can re-open this issue and be better able to assist you.

Thank you!