Problem when following AWS react app learning module

1

I am working through : https://aws.amazon.com/getting-started/hands-on/build-react-app-amplify-graphql/module-one When I get to module 4 to add a GraphQL API that simply involves cutting and pasting the App.js given on the site, then try to run npm start, I get the following compile error(s): ERROR in ./src/App.js 22:26-37 export 'API' (imported as 'API') was not found in 'aws-amplify' (possible exports: Amplify) This error is repeated wherever I reference the API import from aws-amplify. Here is the simple import: import { API } from "aws-amplify"; This has also occurred in another Amplify project I was trying to build so I decided to start from scratch doing something simple directly given from AWS as an example. Why is this happening and how can I fix?

  • The answer you gave fixed the API error. Module 5 in the above example adds storage using import {Storage} frow 'aws-amplify'; This method gives Javascript compiler errors for references to "Storage". I also tried importing Storage from 'aws-amplify/storge' and got the same errors. I see no references as to a new method to do this. How do you do this using the latest interface? Note that the code has references to Storage.get, Storage.put, and Storage.remove.

pjobs
asked 5 months ago1156 views
5 Answers
4
Accepted Answer

I have figured out a working version for https://aws.amazon.com/getting-started/hands-on/build-react-app-amplify-graphql/module-one using Amplify v6. Note that the present example given in the web site above contains several errors. Among them is not having a sufficiently qualified src clause in the Image tag and not having a sufficiently qualified S3 key in the createNote function. Both of these issues are in Module 5. I also believe it is necessary to add S3 permissions to the appropriate Cognito role in order to be able access S3. I have included the completed tested code below. Since I am still a newbee, there may be further optimizations that are desirable. I grant AWS and anyone else unrestricted access to modify and use of the below code.

// From: https://aws.amazon.com/getting-started/hands-on/build-react-app-amplify-graphql/module-two/?e=gs2020&p=build-a-react-app
import React, { useState, useEffect } from "react";
import "./App.css";
import "@aws-amplify/ui-react/styles.css";
import { uploadData, getUrl, remove } from 'aws-amplify/storage';
import {
  Button,
  Flex,
  Heading,
  Image,
  Text,
  TextField,
  View,
  withAuthenticator,
} from "@aws-amplify/ui-react";
import { listNotes } from "./graphql/queries";
import {
  createNote as createNoteMutation,
  deleteNote as deleteNoteMutation,
} from "./graphql/mutations";

// From ChatGPT:
import {Amplify} from 'aws-amplify';
import awsExports from './aws-exports'; // The path may vary
import { generateClient } from 'aws-amplify/api';

Amplify.configure(awsExports);

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.id});
          note.image = 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
    };
    const result=await client.graphql({
      query: createNoteMutation,
      variables: { input: data },
    });
    if (!!data.image) await uploadData({key:result.data.createNote.id, data:image}).result;
    fetchNotes();
    event.target.reset();
  } 

  async function deleteNote({ id, name }) {
    const newNotes = notes.filter((note) => note.id !== id);
    setNotes(newNotes);
    await remove({key:id});
    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.url.href}
              alt={`visual aid for ${note.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);
pjobs
answered 4 months ago
profile picture
EXPERT
reviewed a month ago
1

Sorry about above formatting. I said above I was a newbee. Did not expect reformatting.

// From: https://aws.amazon.com/getting-started/hands-on/build-react-app-amplify-graphql/module-two/?e=gs2020&p=build-a-react-app
import React, { useState, useEffect } from "react";
import "./App.css";
import "@aws-amplify/ui-react/styles.css";
import { uploadData, getUrl, remove } from 'aws-amplify/storage';
import {
  Button,
  Flex,
  Heading,
  Image,
  Text,
  TextField,
  View,
  withAuthenticator,
} from "@aws-amplify/ui-react";
import { listNotes } from "./graphql/queries";
import {
  createNote as createNoteMutation,
  deleteNote as deleteNoteMutation,
} from "./graphql/mutations";

// From ChatGPT:
import {Amplify} from 'aws-amplify';
import awsExports from './aws-exports'; // The path may vary
import { generateClient } from 'aws-amplify/api';

Amplify.configure(awsExports);

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.id});
          note.image = 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
    };
    const result=await client.graphql({
      query: createNoteMutation,
      variables: { input: data },
    });
    if (!!data.image) await uploadData({key:result.data.createNote.id, data:image}).result;
    fetchNotes();
    event.target.reset();
  } 

  async function deleteNote({ id, name }) {
    const newNotes = notes.filter((note) => note.id !== id);
    setNotes(newNotes);
    await remove({key:id});
    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.url.href}
              alt={`visual aid for ${note.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);
pjobs
answered 4 months ago
0

Amplify Documentation with references to both version v5 and v6 Docs In this page they are building the same todo application using the v6 , that you are building . Let me know if any thing else comes up

answered 5 months ago
  • I updated the app with modifications to Amplify v6 as best as I understand them. I believe I have getUrl and uploadData working. The remove method is giving me a 403 Forbidden access denied error. So, I decided to look at permissions on the AWS Management console. I had about six Cognito user pools defined but when I checked Cognito, they weren't there. I am a newbe so this is all simple testing and there is no critical data nor problems recreating things. However, I can still log into my app with the Cognito user I created previously. I think the original login dialog had a drop down that allowed you to pick a user pool for the login. That dialog does not show up. Furthermore, I can still login with the Cognito user I created and can create a new user from the login dialog. I also looked at IAM from the Management Console and do not see any of the users I can login to my app with. Cognito showed the pools and the users I created in a user pool before this weekend. Now it is completely empty. What is going on?

  • Please ignore the stuff on IAM and Cognito. Somehow, my login defaulted to Oregon. instead of US. East. Still problems with the remove method though.

  • I thought I had getUrl and uploadData were working. They are not. All references to S3 are giving me 403 Forbidden errors. I assume everything should be public since I created my graphQL schema using AppSync. I believe my parameter list is correct for these methods. Any hints?

0

Hi ! I hope you are doing well. The error you are encountering is most probably because aws has release the latest version of aws-amplify package . In the example you are following they are using v5 of amplify and you must have downloaded the latest version of amplify i.e v6.

Run these commands in the terminal , this will essentially remove the v6 of the amplify and install the v5 you don't need to perform any code changes. Then

npm uninstall aws-amplify
npm install aws-amplify@5

Let me know if error persists

answered 5 months ago
  • I would like to use the v6 version of this if possible. How do you do this or can you at least point me to some documentation?

  • npm uninstall aws-amplify @aws-amplify/ui-react npm install aws-amplify@5 @aws-amplify/ui-react@5

    The above works as well.

    It would really help if the AWS examples also specify the npm package versions in the documented examples.

0

To update the code from v5 to v6, I needed to update my graphql imports.

Previously v5:

import { API, Storage } from "aws-amplify";

Updated to for v6:

import { generateClient } from 'aws-amplify/api';
const API = generateClient();

Docs for Upgrading v5 to v6 for api-graphql: https://docs.amplify.aws/react/build-a-backend/troubleshooting/migrate-from-javascript-v5-to-v6/#api-graphql

Cole
answered 2 months ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions