Closed greg-munro closed 8 months ago
Hi @greg-munro - thank you for opening this issue. Can you confirm which version of aws-amplify
you have installed? The reason I ask is with the latest version (6.x.x
) released about 2 weeks ago, we no longer export the API class, but instead have a generateClient()
export to setup a client to make the graphql calls. You can view an example of this in our documentation.
@nadetastic i am also following this tutorial and getting the same error. how would this fix be done with the given code from the original post?
Hi @nadetastic, thanks for the quick response. I am using Amplify 6.0.5.
I would suggest the tutorial frontend code needs updating here.
many thanks.
Hi @greg-munro 👋 we are looking into addressing outdated guides that were written for Amplify v5 projects.
@scotttlee , here is what the code from Module 4: Add a GraphQL API and Database would look like if migrated to Amplify JS v6.
import React, { useState, useEffect, FormEvent } from "react";
import {
Button,
Flex,
Heading,
Text,
TextField,
View,
WithAuthenticatorProps,
withAuthenticator,
} from "@aws-amplify/ui-react";
import "./App.css";
import "@aws-amplify/ui-react/styles.css";
import { listNotes } from "../src/graphql/queries";
import {
createNote as createNoteMutation,
deleteNote as deleteNoteMutation,
} from "../src/graphql/mutations";
import { CreateNoteInput, Note } from "@/src/API";
import { Amplify } from "aws-amplify";
import { generateClient } from "aws-amplify/api";
import awsconfig from "@/src/amplifyconfiguration.json";
Amplify.configure(awsconfig);
const client = generateClient();
const App = ({ signOut }: WithAuthenticatorProps) => {
const [notes, setNotes] = useState<Note[]>([]);
useEffect(() => {
fetchNotes();
}, []);
async function fetchNotes() {
const apiData = await client.graphql({ query: listNotes });
const notesFromAPI = apiData.data.listNotes.items;
setNotes(notesFromAPI);
}
async function createNote(event: FormEvent<HTMLFormElement>) {
const form = event.target as HTMLFormElement;
event.preventDefault();
const formData = new FormData(form);
const data: CreateNoteInput = {
name: formData.get("name") as string,
description: formData.get("description") as string,
};
await client.graphql({
query: createNoteMutation,
variables: { input: data },
});
await fetchNotes();
form.reset();
}
async function deleteNote({ id }: Note) {
const newNotes = notes.filter((note) => note.id !== id);
setNotes(newNotes);
await client.graphql({
query: deleteNoteMutation,
variables: { input: { id } },
});
}
return (
<View className="App">
<Heading level={1}>My Notes App</Heading>
<View as="form" margin="3rem 0" onSubmit={createNote}>
<Flex direction="row" justifyContent="center">
<TextField
name="name"
placeholder="Note Name"
label="Note Name"
labelHidden
variation="quiet"
required
/>
<TextField
name="description"
placeholder="Note Description"
label="Note Description"
labelHidden
variation="quiet"
required
/>
<Button type="submit" variation="primary">
Create Note
</Button>
</Flex>
</View>
<Heading level={2}>Current Notes</Heading>
<View margin="3rem 0">
{notes.map((note) => (
<Flex
key={note.id || note.name}
direction="row"
justifyContent="center"
alignItems="center"
>
<Text as="strong" fontWeight={700}>
{note.name}
</Text>
<Text as="span">{note.description}</Text>
<Button variation="link" onClick={() => deleteNote(note)}>
Delete note
</Button>
</Flex>
))}
</View>
<Button onClick={signOut}>Sign Out</Button>
</View>
);
};
export default withAuthenticator(App);
@chrisbonifacio I am running into the same sort of error on another tutorial:
https://aws.amazon.com/getting-started/guides/deploy-webapp-amplify/module-two/?pg=webappamplify
I'm assuming there needs to be a tweak in the contents of the App.js file in here as well to account for the latest version of amplify, I'd love some assistance. Thank you!
@chrisbonifacio I am running into the same sort of error on another tutorial:
https://aws.amazon.com/getting-started/guides/deploy-webapp-amplify/module-two/?pg=webappamplify
I'm assuming there needs to be a tweak in the contents of the App.js file in here as well to account for the latest version of amplify, I'd love some assistance. Thank you!
Personally would like to see an update as well, as I am not able to get past this issue currently
Hello! Sorry for asking this (might be a stupid question):
I already have an application that we did a lot of progress using the v5. Are you guys going to deprecate this version, or make it unable to do any http calls? This is important for us because we're evaluating the migration to v6
I ran into a slightly confusing documentation issue with amplify-aws-react-native
as well. The docs are updated to show the amplify-aws
v6 api yet the latest version of amplify-aws-react-native
only works with v5.
https://docs.amplify.aws/react-native/build-a-backend/graphqlapi/connect-to-api/
I just had to make the following changes to the code in the tutorial:
add:
import { generateClient } from 'aws-amplify/api';
const client = generateClient();
Then change all references from API to client. e.g.
const apiData = await API.graphql({ query: listNotes });
to
const apiData = await client.graphql({ query: listNotes });
Here is my modified code which works in my environment:
// Put your code below this line.
import React, { useState, useEffect } from "react";
import "./App.css";
import "@aws-amplify/ui-react/styles.css";
import {
Button,
Flex,
Heading,
Text,
TextField,
View,
withAuthenticator,
} from "@aws-amplify/ui-react";
import { listNotes } from "./graphql/queries";
import {
createNote as createNoteMutation,
deleteNote as deleteNoteMutation,
} from "./graphql/mutations";
import { generateClient } from 'aws-amplify/api';
const client = generateClient();
const App = ({ signOut }) => {
const [notes, setNotes] = useState([]);
useEffect(() => {
fetchNotes();
}, []);
async function fetchNotes() {
const apiData = await client.graphql({ query: listNotes });
const notesFromAPI = apiData.data.listNotes.items;
setNotes(notesFromAPI);
}
async function createNote(event) {
event.preventDefault();
const form = new FormData(event.target);
const data = {
name: form.get("name"),
description: form.get("description"),
};
await client.graphql({
query: createNoteMutation,
variables: { input: data },
});
fetchNotes();
event.target.reset();
}
async function deleteNote({ id }) {
const newNotes = notes.filter((note) => note.id !== id);
setNotes(newNotes);
await client.graphql({
query: deleteNoteMutation,
variables: { input: { id } },
});
}
return (
<View className="App">
<Heading level={1}>My Notes App</Heading>
<View as="form" margin="3rem 0" onSubmit={createNote}>
<Flex direction="row" justifyContent="center">
<TextField
name="name"
placeholder="Note Name"
label="Note Name"
labelHidden
variation="quiet"
required
/>
<TextField
name="description"
placeholder="Note Description"
label="Note Description"
labelHidden
variation="quiet"
required
/>
<Button type="submit" variation="primary">
Create Note
</Button>
</Flex>
</View>
<Heading level={2}>Current Notes</Heading>
<View margin="3rem 0">
{notes.map((note) => (
<Flex
key={note.id || note.name}
direction="row"
justifyContent="center"
alignItems="center"
>
<Text as="strong" fontWeight={700}>
{note.name}
</Text>
<Text as="span">{note.description}</Text>
<Button variation="link" onClick={() => deleteNote(note)}>
Delete note
</Button>
</Flex>
))}
</View>
<Button onClick={signOut}>Sign Out</Button>
</View>
);
};
export default withAuthenticator(App);
yes, I had the same issues... Technical writing is becoming a lost art... these directions could be stronger.
For anyone that has trouble with Module 5: Add Storage (such as encountering a similar error except with 'Storage'
instead of 'API'
), building on the code that was provided by @rosenzw, here is a solution for displaying images on the app using the updated documentation provided by @nadetastic.
Changes made (following the 'Update the React App' section in Module 5):
import { uploadData, getUrl, remove } from 'aws-amplify/storage';
instead of import { API, Storage } from 'aws-amplify';
.Storage.get(note.name)
and note.image = url
in fetchNotes
with getUrl({ key: note.name })
and note.image = url.url;
respectively.Storage.put(data.name, image)
in createNote
with uploadData({ key: data.name, data: image })
.Storage.remove(name)
in deleteNote
with remove({ key: name })
.Note: A slight issue that the code has right now is that if you just entered into the app with no notes, you need to refresh the page once after you create your first note so the image displays properly. I suspect it has something to do with caching the image, but overall I'm not sure why this happens.
Here is the code below:
import React, { useState, useEffect } from "react";
import "./App.css";
import "@aws-amplify/ui-react/styles.css";
import {
Button,
Flex,
Heading,
Text,
TextField,
Image,
View,
withAuthenticator,
} from "@aws-amplify/ui-react";
import { listNotes } from "./graphql/queries";
import {
createNote as createNoteMutation,
deleteNote as deleteNoteMutation,
} from "./graphql/mutations";
import { generateClient } from 'aws-amplify/api';
import { uploadData, getUrl, remove } from 'aws-amplify/storage';
const client = generateClient();
const App = ({ signOut }) => {
const [notes, setNotes] = useState([]);
useEffect(() => {
fetchNotes();
}, []);
async function fetchNotes() {
const apiData = await client.graphql({ query: listNotes });
const notesFromAPI = apiData.data.listNotes.items;
await Promise.all(
notesFromAPI.map(async (note) => {
if (note.image) {
const url = await getUrl({ key: note.name });
note.image = url.url;
}
return note;
})
);
setNotes(notesFromAPI);
}
async function createNote(event) {
event.preventDefault();
const form = new FormData(event.target);
const image = form.get("image");
const data = {
name: form.get("name"),
description: form.get("description"),
image: image.name,
};
if (!!data.image) await uploadData({
key: data.name,
data: image
});
await client.graphql({
query: createNoteMutation,
variables: { input: data },
});
fetchNotes();
event.target.reset();
}
async function deleteNote({ id, name }) {
const newNotes = notes.filter((note) => note.id !== id);
setNotes(newNotes);
await remove({ key: name });
await client.graphql({
query: deleteNoteMutation,
variables: { input: { id } },
});
}
return (
<View className="App">
<Heading level={1}>My Notes App</Heading>
<View as="form" margin="3rem 0" onSubmit={createNote}>
<Flex direction="row" justifyContent="center">
<TextField
name="name"
placeholder="Note Name"
label="Note Name"
labelHidden
variation="quiet"
required
/>
<TextField
name="description"
placeholder="Note Description"
label="Note Description"
labelHidden
variation="quiet"
required
/>
<View
name="image"
as="input"
type="file"
style={{ alignSelf: "end" }}
/>
<Button type="submit" variation="primary">
Create Note
</Button>
</Flex>
</View>
<Heading level={2}>Current Notes</Heading>
<View margin="3rem 0">
{notes.map((note) => (
<Flex
key={note.id || note.name}
direction="row"
justifyContent="center"
alignItems="center"
>
<Text as="strong" fontWeight={700}>
{note.name}
</Text>
<Text as="span">{note.description}</Text>
{note.image && (
<Image
src={note.image}
alt={`visual aid for ${notes.name}`}
style={{ width: 400 }}
/>
)}
<Button variation="link" onClick={() => deleteNote(note)}>
Delete note
</Button>
</Flex>
))}
</View>
<Button onClick={signOut}>Sign Out</Button>
</View>
);
};
export default withAuthenticator(App);
Hope this helps!
I must say, I'm quite surprised by the complexity and lack of clarity in the AWS documentation, especially around Amplify. Given AWS's reputation for professionalism, I expected a smoother, more intuitive guide, particularly for beginners eager to explore and learn. The current state feels like a bit of a maze and could really benefit from a revamp to make it more accessible and less of a hurdle for newcomers.
Hi @greg-munro - thank you for opening this issue. Can you confirm which version of
aws-amplify
you have installed? The reason I ask is with the latest version (6.x.x
) released about 2 weeks ago, we no longer export the API class, but instead have agenerateClient()
export to setup a client to make the graphql calls. You can view an example of this in our documentation.
Thanks to the good documentation link above, if you follow part of the section "Add Your First Record" and:
too long didn't read (tl;dr): the below code worked for me (and I'm also working on the same AWS tutorial
Don't hesitate to message me with follow-up questions if you have issues!
`import React, { useState, useEffect } from "react"; import "./App.css"; import "@aws-amplify/ui-react/styles.css";
//import { API } from "aws-amplify"; import { generateClient } from 'aws-amplify/api'; import {createTodo, updateTodo, deleteTodo } from './graphql/mutations'; import {listTodos} from './graphql/queries';
import { Button, Flex, Heading, Text, TextField, View, withAuthenticator, } from "@aws-amplify/ui-react"; import { listNotes } from "./graphql/queries"; import { createNote as createNoteMutation, deleteNote as deleteNoteMutation, } from "./graphql/mutations";
const client = generateClient();
const App = ({ signOut }) => { const [notes, setNotes] = useState([]);
useEffect(() => { fetchNotes(); }, []);
async function fetchNotes() { const apiData = await client.graphql({ query: listNotes }); const notesFromAPI = apiData.data.listNotes.items; setNotes(notesFromAPI); }
async function createNote(event) { event.preventDefault(); const form = new FormData(event.target); const data = { name: form.get("name"), description: form.get("description"), }; await client.graphql({ query: createNoteMutation, variables: { input: data }, }); fetchNotes(); event.target.reset(); }
async function deleteNote({ id }) { const newNotes = notes.filter((note) => note.id !== id); setNotes(newNotes); await client.graphql({ query: deleteNoteMutation, variables: { input: { id } }, }); }
return (
); };
export default withAuthenticator(App);`
I just had to make the following changes to the code in the tutorial:
add:
import { generateClient } from 'aws-amplify/api'; const client = generateClient();
Then change all references from API to client. e.g.
const apiData = await API.graphql({ query: listNotes });
toconst apiData = await client.graphql({ query: listNotes });
Here is my modified code which works in my environment:
// Put your code below this line. import React, { useState, useEffect } from "react"; import "./App.css"; import "@aws-amplify/ui-react/styles.css"; import { Button, Flex, Heading, Text, TextField, View, withAuthenticator, } from "@aws-amplify/ui-react"; import { listNotes } from "./graphql/queries"; import { createNote as createNoteMutation, deleteNote as deleteNoteMutation, } from "./graphql/mutations"; import { generateClient } from 'aws-amplify/api'; const client = generateClient(); const App = ({ signOut }) => { const [notes, setNotes] = useState([]); useEffect(() => { fetchNotes(); }, []); async function fetchNotes() { const apiData = await client.graphql({ query: listNotes }); const notesFromAPI = apiData.data.listNotes.items; setNotes(notesFromAPI); } async function createNote(event) { event.preventDefault(); const form = new FormData(event.target); const data = { name: form.get("name"), description: form.get("description"), }; await client.graphql({ query: createNoteMutation, variables: { input: data }, }); fetchNotes(); event.target.reset(); } async function deleteNote({ id }) { const newNotes = notes.filter((note) => note.id !== id); setNotes(newNotes); await client.graphql({ query: deleteNoteMutation, variables: { input: { id } }, }); } return ( <View className="App"> <Heading level={1}>My Notes App</Heading> <View as="form" margin="3rem 0" onSubmit={createNote}> <Flex direction="row" justifyContent="center"> <TextField name="name" placeholder="Note Name" label="Note Name" labelHidden variation="quiet" required /> <TextField name="description" placeholder="Note Description" label="Note Description" labelHidden variation="quiet" required /> <Button type="submit" variation="primary"> Create Note </Button> </Flex> </View> <Heading level={2}>Current Notes</Heading> <View margin="3rem 0"> {notes.map((note) => ( <Flex key={note.id || note.name} direction="row" justifyContent="center" alignItems="center" > <Text as="strong" fontWeight={700}> {note.name} </Text> <Text as="span">{note.description}</Text> <Button variation="link" onClick={() => deleteNote(note)}> Delete note </Button> </Flex> ))} </View> <Button onClick={signOut}>Sign Out</Button> </View> ); }; export default withAuthenticator(App);
Thank you. this worked for me
@rosenzw thank you for providing the solution! I'll go ahead and mark this issue as closed.
@chrisbonifacio I am running into the same sort of error on another tutorial: https://aws.amazon.com/getting-started/guides/deploy-webapp-amplify/module-two/?pg=webappamplify I'm assuming there needs to be a tweak in the contents of the App.js file in here as well to account for the latest version of amplify, I'd love some assistance. Thank you!
Personally would like to see an update as well, as I am not able to get past this issue currently
No fix after 5 months! What a waste of people's time. This suggests Amplify is not something to be taken seriously.
@chrisbonifacio I am running into the same sort of error on another tutorial:
https://aws.amazon.com/getting-started/guides/deploy-webapp-amplify/module-two/?pg=webappamplify
I'm assuming there needs to be a tweak in the contents of the App.js file in here as well to account for the latest version of amplify, I'd love some assistance. Thank you!
Although these issues aren't yet updated with the aws-amplify 6.x.x code in the modules, please see the refactors given by @rosenzw and @Bruce-8 for API and Storage respectively: https://github.com/aws-amplify/amplify-js/issues/12635#issuecomment-1873035673 https://github.com/aws-amplify/amplify-js/issues/12635#issuecomment-1875954882
Before opening, please confirm:
JavaScript Framework
React
Amplify APIs
GraphQL API
Amplify Categories
api
Environment information
Describe the bug
I am following the build a full stack React app tutorial here (https://aws.amazon.com/getting-started/hands-on/build-react-app-amplify-graphql/module-four/?e=gs2020&p=build-a-react-app-three) and module 4 results in the error, saying the API from amplify is not found.
Expected behavior
Code to run on npm start
Reproduction steps
Follow the steps in module 4 and run npm start
Code Snippet
Log output
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