diff --git a/legacy/aws-amplify-react/README.md b/legacy/aws-amplify-react/README.md index 934fe15ec17..b8821bdac60 100644 --- a/legacy/aws-amplify-react/README.md +++ b/legacy/aws-amplify-react/README.md @@ -3,3 +3,1062 @@ AWS Amplify is a JavaScript library for frontend and mobile developers building cloud-enabled applications. The library is a declarative interface across different categories of operations in order to make common tasks easier to add into your application. The default implementation works with Amazon Web Services (AWS) resources but is designed to be open and pluggable for usage with other cloud services that wish to provide an implementation or custom backends. `aws-amplify-react` is one of the AWS Amplify library packages, provide building blocks for React App development. Documentation is available [here](https://github.com/aws-amplify/amplify-js/blob/main/README.md) + +## Installation + +``` +yarn add aws-amplify aws-amplify-react +``` + +--- + +# Authenticator + +## Using withAuthenticator HOC + +For React, the simplest way to add authentication flows into your app is to use the `withAuthenticator` Higher Order Component. + +`withAuthenticator` automatically detects the authentication state and updates the UI. If the user is signed in, the underlying component (typically your app's main component) is displayed otherwise signin/signup controls are displayed. + +> The default implementation uses the Amplify UI styling, for an example of what that looks like out of the box on web and mobile, see here. + +Just add these two lines to your `App.js`: + +```javascript +import { withAuthenticator } from 'aws-amplify-react'; // or 'aws-amplify-react-native'; +import Amplify from 'aws-amplify'; +// Get the aws resources configuration parameters +import awsconfig from './aws-exports'; // if you are using Amplify CLI + +Amplify.configure(awsconfig); + +// ... + +export default withAuthenticator(App); +``` + +Now, your app has complete flows for user sign-in and registration. Since you have wrapped your **App** with `withAuthenticator`, only signed in users can access your app. The routing for login pages and giving access to your **App** Component will be managed automatically. + +`withAuthenticator` component renders your App component after a successful user signed in, and it prevents non-sign-in users to interact with your app. In this case, we need to display a _sign-out_ button to trigger the related process. + +To display a sign-out button or customize other, set `includeGreetings = true` in the parameter object. It displays a _greetings section_ on top of your app, and a sign-out button is displayed in the authenticated state. Other customization options are also available as properties to the HOC: + +```jsx +export default withAuthenticator(App, { + // Render a sign out button once logged in + includeGreetings: true, + // Show only certain components + authenticatorComponents: [MyComponents], + // display federation/social provider buttons + federated: { myFederatedConfig }, + // customize the UI/styling + theme: { myCustomTheme }, +}); +``` + +## Using the Authenticator Component + +The `withAuthenticator` HOC wraps an `Authenticator` component. Using `Authenticator` directly gives you more customization options for your UI. + +```jsx + console.log(authState)} + // An object referencing federation and/or social providers + // The federation here means federation with the Cognito Identity Pool Service + // *** Only supported on React/Web (Not React Native) *** + // For React Native use the API Auth.federatedSignIn() + federated={myFederatedConfig} + // A theme object to override the UI / styling + theme={myCustomTheme} + // Hide specific components within the Authenticator + // *** Only supported on React/Web (Not React Native) *** + hide={[ + Greetings, + SignIn, + ConfirmSignIn, + RequireNewPassword, + SignUp, + ConfirmSignUp, + VerifyContact, + ForgotPassword, + TOTPSetup, + Loading, + ]} + // or hide all the default components + hideDefault={true} + // Pass in an aws-exports configuration + amplifyConfig={myAWSExports} + // Pass in a message map for error strings + errorMessage={myMessageMap} +> + // Default components can be customized/passed in as child components. // + Define them here if you used hideDefault={true} + + + + + + + + + + + +``` + +## Customize your own components + +You can provide custom components to the `Authenticator` as child components in React and React Native. + +```jsx +import { Authenticator, SignIn } from 'aws-amplify-react'; + +// The override prop tells the Authenticator that the SignUp component is not hidden but overridden + + + +; + +class MyCustomSignUp extends Component { + constructor() { + super(); + this.gotoSignIn = this.gotoSignIn.bind(this); + } + + gotoSignIn() { + // to switch the authState to 'signIn' + this.props.onStateChange('signIn', {}); + } + + render() { + return ( +
+ {/* only render this component when the authState is 'signUp' */} + {this.props.authState === 'signUp' && ( +
+ My Custom SignUp Component + +
+ )} +
+ ); + } +} +``` + +You can render the custom component (or not) based on the injected `authState` within your component as well as jump to other states within your component. + +```jsx +if (props.onStateChange) props.onStateChange(state, data); +``` + +To customize the UI for Federated Identities sign-in, you can use `withFederated` component. The following code shows how you customize the login buttons and the layout for social sign-in. + +> **_The withFederated and Federated components are not supported on React Native_**. Use the API Auth.federatedSignIn() on React Native. + +```javascript +import { withFederated } from 'aws-amplify-react'; + +const Buttons = (props) => ( +
+ + + +
+) + +const Federated = withFederated(Buttons); + +... + +const federated = { + google_client_id: '', // Enter your google_client_id here + facebook_app_id: '', // Enter your facebook_app_id here + amazon_client_id: '' // Enter your amazon_client_id here +}; + + +``` + +There is also `withGoogle`, `withFacebook`, `withAmazon` components, in case you need to customize a single provider. + +### Wrapping your Component + +This will render your App component with _Authenticator_: + +```javascript +import { Authenticator } from 'aws-amplify-react'; // or 'aws-amplify-react-native' +... + +class AppWithAuth extends Component { + render(){ + return ( +
+ + + +
+ ); + } +} + +export default AppWithAuth; +``` + +## Show your App After Sign-in + +In the previous example, you'll see the App is rendered even before the user is signed-in. To change this behavior, you can use _Authenticator_ properties. When inside `Authenticator`, the App component automatically receives those properties. + +**authState** is the current authentication state (a string): + +``` + - signIn + - signUp + - confirmSignIn + - confirmSignUp + - forgotPassword + - requireNewPassword + - verifyContact + - signedIn +``` + +**authData** - additional data within authState; when the state is `signedIn`, it will return a [`CognitoUser`](https://github.com/aws-amplify/amplify-js/blob/main/packages/amazon-cognito-identity-js/index.d.ts#L48) object. + +Using the options above, to control the condition for _Authenticator_ to render App component, simply set `_validAuthStates` property: + +```javascript +this._validAuthStates = ['signedIn']; +``` + +Then, in the component's constructor, implement `showComponent(theme) {}` in lieu of the typical `render() {}` method. + +## SignUp + +The SignUp component provides your users with the ability to sign up. It is included as part of the `Authenticator` component. + +Usage: +`` + +It can also be used as part of the authentication HOC: +`export default withAuthenticator(App, { signUpConfig });` + +The SignUp Component accepts a 'signUpConfig' object which allows you to customize it. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AttributeTypeDescriptionDefaultRequired
headerstringthe component header'Create a new account'no
signUpFieldsarraysee belowsee belowno
defaultCountryCodestring + the preselected value in the country code dropdown + '1'no
hideAllDefaultsboolean + determines whether all default signup fields are to be hidden. This + works in conjunction with the signUpFields attribute + + if there is no signUpFields attribute, defaults to false + no
hiddenDefaultsarray + determines whether particular default fields are hidden + + N/A (possible values include 'username', 'password', 'phone_number', and + 'email') + no
+ +The signUpFields array in turn consist of an array of objects, each describing a field that will appear in sign up form that your users fill out: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AttributeTypeDescriptionPossible Values
labelstringlabel for the input fieldN/A
keystringkey name for the attribute as defined in the User PoolN/A
requiredbooleanwhether or not the field is requiredN/A
displayOrdernumbernumber indicating the order in which fields will be displayedN/A
typestringthe type attribute for the html input element‘string’, ‘number’, ‘password’, etc
custombooleanflag which indicates whether or not the field is ‘custom’ in the User PoolN/A
+ +A Sample signUpFields attribute would look like the following: + +```js +const signUpConfig = { + header: 'My Customized Sign Up', + hideAllDefaults: true, + defaultCountryCode: '1', + signUpFields: [ + { + label: 'My custom email label', + key: 'email', + required: true, + displayOrder: 1, + type: 'string' + }, + ... // and other custom attributes + ] +}; + +export default withAuthenticator(App, { signUpConfig }); +``` + +## Sign up/in with email/phone number + +If the user pool is set to allow email addresses/phone numbers as the username, you can then change the UI components accordingly by using `usernameAttributes` [(learn more about the setup)](https://docs.amplify.aws/lib/auth/getting-started/q/platform/js). + +When you are using `email` as the username: + +```js +import { withAuthenticator, Authenticator } from 'aws-amplify-react'; + +// When using Authenticator +class App { + // ... + + render() { + return ( + + ); + } +} + +export default App; + +// When using withAuthenticator +class App2 { + // ... +} + +export default withAuthenticator(App2, { usernameAttributes: 'email' }); +``` + +When you are using `phone number` as the username: + +```js +import { Authenticator, withAuthenticator } from 'aws-amplify-react'; + +class App { + // ... + + render() { + return ( + + ); + } +} + +export default App; + +// When using withAuthenticator +class App2 { + // ... +} + +export default withAuthenticator(App2, { usernameAttributes: 'phone_number' }); +``` + +**Note:** If you are using custom signUpFields to customize the `username` field, then you need to make sure either the label of that field is the same value you set in `usernameAttributes` or the key of the field is `username`. + +For example: + +```js +import React, { Component } from 'react'; +import Amplify from 'aws-amplify'; +import awsconfig from './aws-exports'; +import { withAuthenticator } from 'aws-amplify-react'; + +Amplify.configure(awsconfig); + +class App extends Component {} + +const signUpConfig = { + header: 'My Customized Sign Up', + hideAllDefaults: true, + defaultCountryCode: '1', + signUpFields: [ + { + label: 'My user name', + key: 'username', + required: true, + displayOrder: 1, + type: 'string', + }, + { + label: 'Password', + key: 'password', + required: true, + displayOrder: 2, + type: 'password', + }, + { + label: 'PhoneNumber', + key: 'phone_number', + required: true, + displayOrder: 3, + type: 'string', + }, + { + label: 'Email', + key: 'email', + required: true, + displayOrder: 4, + type: 'string', + }, + ], +}; +const usernameAttributes = 'My user name'; + +export default withAuthenticator(App, { + signUpConfig, + usernameAttributes, +}); +``` + +--- + +# API - Connect + +The API category provides React components for working with GraphQL data using the Amplify GraphQL client. + +The `` component is used to execute a GraphQL query or mutation. You can execute GraphQL queries by passing your queries in `query` or `mutation` attributes: + +## Queries + +```javascript +import React, { Component } from 'react'; +import Amplify, { graphqlOperation } from 'aws-amplify'; +import { Connect } from 'aws-amplify-react'; + +import * as queries from './graphql/queries'; +import * as subscriptions from './graphql/subscriptions'; + +class App extends Component { + render() { + const ListView = ({ todos }) => ( +
+

All Todos

+
    + {todos.map((todo) => ( +
  • + {todo.name} ({todo.id}) +
  • + ))} +
+
+ ); + + return ( + + {({ data: { listTodos }, loading, errors }) => { + if (errors) return

Error

; + if (loading || !listTodos) return

Loading...

; + return ; + }} +
+ ); + } +} + +export default App; +``` + +## Subscription + +Also, you can use the `subscription` and `onSubscriptionMsg` attributes to enable subscriptions: + +```javascript + { + console.log(onCreateTodo); + return prev; + }} +> + {({ data: { listTodos }, loading, error }) => { + if (error) return

Error

; + if (loading || !listTodos) return

Loading...

; + return ; + }} +
+``` + +## Mutations + +For mutations, a `mutation` function needs to be provided with the `Connect` component. A `mutation` returns a promise that resolves with the result of the GraphQL mutation. + +```jsx +import React, { Component } from 'react'; +import * as mutations from './graphql/mutations'; +import * as queries from './graphql/queries'; +import * as subscriptions from './graphql/subscriptions'; + +class AddTodo extends Component { + constructor(props) { + super(props); + this.submit = this.submit.bind(this); + this.state = { + name: '', + description: '', + }; + } + + handleChange(name, event) { + this.setState({ [name]: event.target.value }); + } + + async submit() { + const { onCreate } = this.props; + const input = { + name: this.state.name, + description: this.state.description, + }; + console.log(input); + + try { + await onCreate({ input }); + } catch (err) { + console.error(err); + } + } + + render() { + return ( +
+ { + this.handleChange('name', event); + }} + /> + { + this.handleChange('description', event); + }} + /> + +
+ ); + } +} + +class App extends Component { + render() { + const ListView = ({ todos }) => ( +
+

All Todos

+
    + {todos.map((todo) => ( +
  • {todo.name}
  • + ))} +
+
+ ); + + return ( +
+ + {({ mutation }) => } + + + { + console.log('Subscription data:', onCreateTodo); + return prev; + }} + > + {({ data: { listTodos }, loading, error }) => { + if (error) return

Error

; + if (loading || !listTodos) return

Loading...

; + return ; + }} +
+
+ ); + } +} +``` + +--- + +# Storage + +## Photo Picker + +`Picker` is used to pick a file from local device storage. `PhotoPicker` and `TextPicker` components are specific to image and text file types . + +![Image](photo_picker_and_code.png) + +Listen to `PhotoPicker` onPick event: + +```jsx +import { PhotoPicker } from 'aws-amplify-react'; + +render() { + console.log(data)} /> +} +``` + +To display a preview, you can use `preview` directive: + +```jsx + console.log(dataURL)} /> +``` + +You can retrieve the URL of the image by implementing `onLoad` action. In this case, you may also want to hide the preview: + +```jsx + console.log(dataURL)} /> +``` + +## S3 Album + +`S3Album` renders a list of `S3Image` and `S3Text` objects: + +![Image](S3Album_and_code.png) + +```jsx +import { S3Album } from 'aws-amplify-react'; + +render() { + return +``` + +To display private objects, supply the `level` property: + +```jsx +return ; +``` + +To display another user's protected objects, supply that user's `identityId` property as well: + +```jsx +return ; +``` + +You can use `filter` property customize the path for your album: + +```jsx +return ( + /jpg/i.test(item.path)} + /> +); +``` + +**Picker** + +Set `picker` property to true on `S3Album`. A `Picker` let user select photos or text files from the device. The selected files will be automatically uploaded to the `path`. + +```jsx + +``` + +By default, photo picker saves images on S3 with filename as the key. To have custom keys, you can provide a callback: + +```jsx +function fileToKey(data) { + const { name, size, type } = data; + return 'test_' + name; +} + +... + +``` + + + +`S3Album` will escape all spaces in key value to underscore. For example, 'a b' will be converted to 'a_b'. + + + +## S3 Image + +`S3Image` component renders an _Amazon S3 object key_ as an image: + +```jsx +import { S3Image } from 'aws-amplify-react'; + +render() { + return +} +``` + +For private images, supply the `level` property: + +```jsx +return ; +``` + +To show another user's protected image, supply that user's `identityId` property as well: + +```jsx +return ; +``` + +To initiate an upload, set the `body` property: + +```jsx +import { S3Image } from 'aws-amplify-react'; + +render() { + return +} + +``` + +To hide the image shown in the S3Image, set `hidden`: + +```jsx +import { S3Image } from 'aws-amplify-react'; + +render() { + return