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
질문됨 5달 전1260회 조회
5개 답변
4
수락된 답변

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
답변함 5달 전
profile picture
전문가
검토됨 한 달 전
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
답변함 5달 전
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

답변함 5달 전
  • 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

답변함 5달 전
  • 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
답변함 3달 전

로그인하지 않았습니다. 로그인해야 답변을 게시할 수 있습니다.

좋은 답변은 질문에 명확하게 답하고 건설적인 피드백을 제공하며 질문자의 전문적인 성장을 장려합니다.

질문 답변하기에 대한 가이드라인

관련 콘텐츠