Front-End Web & Mobile

NEW in Amplify DataStore: Selective sync and sort functionality

AWS Amplify is the fastest and easiest way to build cloud-powered mobile and web apps on AWS. Amplify comprises a set of tools and services that enables front-end web and mobile developers to leverage the power of AWS services to build innovative and feature-rich applications.

Amplify DataStore (JavaScript, Android, and iOS) provides frontend web and and mobile developers a persistent on-device storage repository for you to write, read, and observe changes to data even if you are online or offline, and seamlessly sync to the cloud as well as across devices. With the recent Amplify Library release, DataStore gains the ability to selectively sync a subset of your app data and to sort your app data.

What’s New:

  • Selectively sync: Only sync a subset of your app data to the local device based on dynamic predicates. For example, you can choose to only sync data based on a logged-in user’s information. By only syncing the data that the end-user needs, customers can also optimize their app’s network efficiency.
  • Sort capability: Sort your app data in ascending or descending order. DataStore also supports multi-level sorting. For example: First sort the ”contacts” ascending by their “workplace” and then descending by their “last names”. No additional changes to your app’s GraphQL schema are required to take advantage of data sorting.

What we’ll build & learn:

  • A “Favorite song playlist” React app that enables a user to add their favorite songs (name + genre)
  • How to ensure to only synchronize the songs downstream of the user’s preferred genre
  • How to enable alphabetical sorting of songs by name

Prerequisites:

  • Install the latest Amplify CLI version
    • Using NPM: npm install -g @aws-amplify/cli
    • cURL on Linux and Mac: curl -sL https://aws-amplify.github.io/amplify-cli/install | bash && $SHELL
    • cURL on Windows: curl -sL https://aws-amplify.github.io/amplify-cli/install-win -o install.cmd && install.cmd
  • Amplify is already configured
    • If you haven’t configured the Amplify CLI yet, follow this guide on our documentation page

Setup a new React project

Run the following command to create a new Amplify project called “songs” or if you already have an existing Amplify project skip to the next section.

npx create-react-app songs
cd songs

Setup your app backend with Amplify CLI

Initialize an Amplify project by running:

amplify init

For the purposes of this blog post, you can just accept all the default values in the amplify init workflow.

Let’s add a GraphQL API to sync your app data to the cloud. Run the following command:

amplify add api

and select the following options.

? Please select from one of the below mentioned services: GraphQL
? Provide API name: songs
? Choose the default authorization type for the API API key
? Enter a description for the API key:
? After how many days from now the API key should expire (1-365): 7

IMPORTANT: Make sure to select the following options to correctly enable DataStore. DataStore requires conflict resolution to be enabled.

? 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
? 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)

Go to amplify/backend/api/songs/schema.graphql and edit your app’s data model:

type Song @model {
  id: ID!
  name: String!
  genre: String!
}

For this example, we’ll keep it simple. You have a “Song” model that has a field called “name” a field called “genre”.

Now that you have your schema set up, let’s deploy your app backend. Run the following command and accept all defaults:

amplify push

Your app backend is successfully deployed! Let’s move on to our client-side code.

Install and initialize the Amplify libraries

Run the following command to install the Amplify libraries:

npm install aws-amplify

In your index.js initialize the Amplify library by adding the following lines of code:

import Amplify from 'aws-amplify'
import awsconfig from './aws-exports'

Amplify.configure(awsconfig)

Setup your app’s UI code

Replace your App.js file with the following content:

import { DataStore, Predicates, SortDirection, syncExpression } from 'aws-amplify'
import { Song } from './models'
import { useEffect, useState, useCallback } from 'react';

// TODO: Configure selective sync

function App() {
  const [sortDir, setSortDir] = useState(SortDirection.ASCENDING)
  const [songs, setSongs] = useState([])
  const [name, setName] = useState('')
  const [genre, setGenre] = useState('')

  // TODO: Update later with sort functionality
  const querySongs = useCallback(async () => { 
    setSongs(await DataStore.query(Song))
  }, [])

  useEffect(() => querySongs(), [querySongs])

  return (
    <div className="App">
      <div>
        <h2>My Songs</h2>
        <div>
          Sort: 
          <select value={sortDir} onChange={(e) => setSortDir(e.target.value)}>
            <option value={SortDirection.ASCENDING}>A to Z</option>
            <option value={SortDirection.DESCENDING}>Z to A</option>
          </select>
          <button onClick={() => querySongs()}>Refresh</button>
        </div>
        <ul>
          {songs.map(song => <li key={song.id}>{song.name} - {song.genre}</li>)}
        </ul>
      </div>
      <div>
        <h2>Add new song</h2>
        <input type='text' placeholder='name' value={name} onChange={e => setName(e.target.value)}></input>
        <input type='text' placeholder='genre' value={genre} onChange={e => setGenre(e.target.value)}></input>
        <button onClick={async () => {
          const toAddSong = new Song({ name, genre })
          await DataStore.save(toAddSong)
          querySongs()
          setName('')
          setGenre('')
        }}>Add</button>
      </div>
    </div>
  );
}

export default App;

Test your app on your local machine by running:

npm start

This serves you an app to add new song entries and list them. Play around with the app and add a few songs from your favorite genres.

Selectively sync your app data based on active functionality

By default, DataStore downloads the entire contents of your cloud data source to your local device. You can now limit what data DataStore should sync based on customizable conditions.

Let’s say, we want to only sync “Songs” if they are from the “Hip Hop” genre. To do that, we have to configure our DataStore to filter its sync expressions based on the preferred genre.

Update the TODO: Configure selective sync section to include a DataStore Sync Expression configuration. In there, we will define that DataStore should only sync “Song” records whose genre is “Hip Hop“.

DataStore.configure({
  syncExpressions: [syncExpression(Song, s => s.genre('eq', 'Hip Hop'))]
})

Now, the user’s song will only be syncing when the genre is “Hip Hop”. To demonstrate this, clear the web app’s local storage from the dev tools and refresh the web app and re-query. You’ll see how only songs matching the sync expression showing up.

Note: you can also clear the DataStore by calling DataStore.clear().

I’ve simplified the workflow for the purpose of this demo but you can actually reconfigure the sync expressions during runtime. Refer to the documentation for more details on selective sync runtime updates.

Sort your DataStore queries

To sort your app data, we have a new “sort” expression that you can pass in the DataStore.query API call.

  // Queries for items -- TODO: Update later with sort functionality
    const querySongs = useCallback(async () => { 
    setSongs(await DataStore.query(Song, Predicates.ALL, {
      sort: s => s.name(sortDir)
    }))
  }, [sortDir])

You can specify the the Sort Direction either as “SortDirection.ASCENDING” or “SortDirection.DESCENDING”.

In addition to a simple sorting as above, you can setup “multi-level” sorting. For example: “First sort by the name field ascending and then by the genre field descending”. Review our documentation for multi-level sort.

? Success!

This blog post demonstrates how you can selectively sync a subset of your app data with Amplify DataStore and also the new sort capability. There is so much more to Amplify DataStore! Here are some other cool features you’ll want to check out:

Look out for future blog posts on Amplify DataStore and review our documentation for DataStore selective sync and sort capabilities for more details.