Amplify DataStore provides a persistent on-device storage repository for you to write, read, and observe changes to data if you are online or offline, and seamlessly sync to the cloud as well as across devices.
It is free, open source, and supported by the AWS Amplify team, and I wanted to show you how easy it is to use it to add realtime, offline first CRUD features to your app! We'll use React in this example, but you can easily use this guide for adding realtime, offline-first CRUD to an app built with any framework.
100 Second Video Version
Youtube: https://youtu.be/pSSfTWqSXbU
Dev.to Embed:
Text Based Version - 3 Steps
The stuff below is the script for the video above, so you can copy/paste!
Step 1: Setup the React Chat App
Assuming you have setup the Amplify CLI, we're going to spin up a standard React app and install a special demo Chat component I've prepared under the react-demos
package:
npx create react-app amplifychatapp
cd amplifychatapp
yarn add react-demos # or npm install react-demos
Let's try out this demo component to get familiar with it!
// src/App.js
import React from 'react'
import { Chat, useChatLocalState } from 'react-demos'
export default function App() {
const {
currentUser,
sendMessage,
loginUser,
messages,
usersOnline,
} = useChatLocalState()
return (
<div>
<Chat
{...{
currentUser,
sendMessage,
loginUser,
messages,
usersOnline,
}}
/>
</div>
)
}
Now we can start up our app with npm run start
and it works! This data isn't stored or shared though - when you reload that page or load it in an incognito browser, the messages start over from scratch. Not much of a chat app!
Step 2: Setup the Amplify DataStore
We'll init a new Amplify project and amplify add api
, making sure to enable "Conflict Resolution" (which enables the Amplify DataStore):
yarn add aws-amplify @aws-amplify/datastore
# or use npm install
amplify init
# go with all default answers... and when you are done...
amplify add api
? Please select from one of the below mentioned services: GraphQL
? Provide API name: # Any Name Is Fine
? Choose the default authorization type for the API API key
? Enter a description for the API key: # Any Description Is Fine
? After how many days from now the API key should expire (1-365): 7
? Do you want to configure advanced settings for the GraphQL API Yes, I want to make some additional changes.
? Configure additional auth types? No
? Configure conflict detection? Yes # IMPORTANT
? Select the default resolution strategy Auto Merge
? Do you have an annotated GraphQL schema? No
? Choose a schema template: Single object with fields (e.g., βTodoβ with ID, name, description)
# some instructions here...
? Do you want to edit the schema now? Yes
This will open up your editor where we can specify the GraphQL schema for the DataStore (it is exactly the same schema definition language as GraphQL Transform for AWS AppSync). We'll paste in this very simple schema:
# /amplify/backend/api/YOURAPINAME/schema.graphql
type User @model {
id: ID!
name: String
}
type Message @model {
id: ID!
user: String
text: String
}
Save the file and amplify push --y
to kick off provisioning the AWS backend!
While that's going, we will run amplify codegen models
to generate the DataStore models we will use in our React app.
Step 3: Wire up DataStore with React
Now let's put it into use:
import React from "react";
import { DataStore } from "@aws-amplify/datastore";
import { User, Message } from "./models";
import { Chat } from "react-demos";
import Amplify from 'aws-amplify';
import awsconfig from './aws-exports';
Amplify.configure(awsconfig); // will not sync if you forget this
function App() {
const [currentUser, setCurrentUser] = React.useState(null);
const [usersOnline, setUsersOnline] = React.useState([]);
const [messages, setMessages] = React.useState([]);
React.useEffect(() => {
fetchMessage();
DataStore.observe(Message).subscribe(fetchMessage);
}, []);
React.useEffect(() => {
fetchMessage();
DataStore.observe(User).subscribe(() =>
DataStore.query(User).then(setUsersOnline)
);
}, []);
async function fetchMessage() {
const _Messages = await DataStore.query(Message);
setMessages(_Messages);
}
async function loginUser(name) {
const user = await DataStore.save(new User({ name }));
setCurrentUser(user);
}
async function sendMessage(text) {
await DataStore.save(
new Message({
user: currentUser.name,
text,
})
);
}
return (
<div>
<Chat
{...{
currentUser,
sendMessage,
loginUser,
messages,
usersOnline,
}}
/>
</div>
);
}
export default App;
And there you have it - a realtime, offline persisting chat app with Amplify DataStore!
Conclusion
Now you've had a taste, be sure to head to the docs to get a fuller understanding, or watch Richard Threlkeld's Re:Invent 2019 talk where Amplify DataStore was first introduced!
P.S. if you are worried about incurring AWS charges following this guide, just run
amplify delete
at the end to delete everything you just set up in one command! The Amplify DataStore itself carries no charge to use, but it uses AWS AppSync for storage so you should check that pricing as you plan for production usage.
Share
Liked this format/tutorial/video? Got requests for more? Please comment and share it with a Tweet or subscribe to my YouTube!
Top comments (8)
One big issue with DataStore: github.com/aws-amplify/amplify-js/...
We're actually finishing up some service changes that will allow you to do this, along with some configuration options in the client. The feedback in that thread was very helpful as requirements for the work. Keep an eye out on that thread in the coming month or so for an update.
it's been fixed now, as seen in the bottom of that thread.
this is a very important issue indeed. unfortunately I have no updates to offer on this one at the moment.
Hi swyx, is this tutorial still in effect? I wonder I followed it but got
`ompiled with problems:X
ERROR in ./src/App.js 12:0-17
export 'default' (imported as 'Amplify') was not found in 'aws-amplify' (possible exports: API, APIClass, AWSCloudWatchProvider, AWSKinesisFirehoseProvider, AWSKinesisProvider, AWSPinpointProvider, AmazonPersonalizeProvider, Amplify, Analytics, Auth, AuthModeStrategyType, Cache, ClientDevice, DataStore, Geo, Hub, I18n, Interactions, Logger, Notifications, Predicates, Predictions, PubSub, ServiceWorker, Signer, SortDirection, Storage, StorageClass, XR, graphqlOperation, syncExpression, withSSRContext)
`
Thank you, if you can cast me a littel light.
@swyx How could we send email notifications if the user is offline when chat? Is that possible?
Thanks for this!
Still having difficulty getting Datastore to work with 1:N relationships
have you filed an issue somewhere i can look up? best way to give AWS feedback is via github issues