Skip to content

Latest commit

 

History

History
127 lines (95 loc) · 5.02 KB

File metadata and controls

127 lines (95 loc) · 5.02 KB

AWS Amplify React Router Adapter

This package contains the AWS Amplify React Router Adapter.

Install

npm add aws-amplify amplify-adapter-react-router

Usage

Configure Amplify in React Router

Configure Amplify for server-side usage

You will need to create a runWithAmplifyServerContext function to use Amplify APIs on the server-side of your React Router app.

You can create an amplifyServerUtils.ts file under a lib folder in your codebase. In this file, you will import the Amplify backend outputs from the amplify_outputs.json file that is generated by the Amplify, and use the createServerRunner function to create the runWithAmplifyServerContext function.

For example, the lib/amplifyServerUtils.ts file may contain the following content:

import { createServerRunner } from "amplify-adapter-react-router";
import outputs from "@/amplify_outputs.json";

export const { runWithAmplifyServerContext } = createServerRunner({
  config: outputs,
});

Generate the Data client for React Router server runtimes

To generate a data client for the React Router server runtime using request and responseHeaders, you only need to provide your Amplify configuration. When making the individual API requests, you will need to pass the config to the runWithAmplifyServerContext function to pass in the cookies from request and responseHeaders variables.

You can create an amplify-ssr-client.ts file under a lib folder in your codebase. In this file, you will import the Amplify backend outputs from the amplify_outputs.json file that is generated by the Amplify, and use the generateClient function imported from aws-amplify/api/server module to create the data client.

For example, the lib/amplify-ssr-client.ts file may contain the following content:

import type { Schema } from "amplify/data/resource";
import { parseAmplifyConfig } from "aws-amplify/utils";
import { generateClient } from "aws-amplify/api/server";
import config from "../../amplify_outputs.json";

const amplifyConfig = parseAmplifyConfig(config);
export const client = generateClient<Schema>({
  config: amplifyConfig,
});

Configure Amplify for client-side usage

When you use the Amplify library on the client-side of your React Router app, you will need to configure Amplify by calling the Amplify.configure as you would to use Amplify in a single-page application.

Note: To use the Amplify library on the client side in a React Router app, you will need to set ssr to true when calling Amplify.configure. This instructs the Amplify library to store tokens in the cookie store of a browser. Cookies will be sent along with requests to your React Router server for authentication.

import outputs from "@/amplify_outputs.json";
import { Amplify } from "aws-amplify";

Amplify.configure(outputs, {
  ssr: true, // required when using Amplify with React Router Framework SSR
});

Calling Amplify category APIs on the server side

For the GraphQL API categories to use Amplify APIs on the server in your React Router app, you will need to:

  1. Use the runWithAmplifyServerContext helper function created by calling the createServerRunner function exported from amplify-adapter-react-router to call the Amplify API in an isolated server context.

Now, you can use the runWithAmplifyServerContext function to call Amplify APIs in an isolated server context. Create a new route app/routes/index.tsx and use runWithAmplifyServerContext in the loader function to call methods of the Amplify Data client, with the following code:

import type { Route } from "./+types/index";
import { TodoList } from "~/components/TodoList";
import { runWithAmplifyServerContext } from "~/lib/amplifyServerUtils";
import { data, Link } from "react-router";
import { client } from "~/lib/amplify-ssr-client";

export function meta() {
  return [
    { title: "React Router Todo App" },
    { name: "description", content: "Todo List" },
  ];
}

export async function loader({ request }: Route.LoaderArgs) {
  const responseHeaders = new Headers();
  const { data: todos, errors } = await runWithAmplifyServerContext({
    serverContext: { request, responseHeaders },
    operation: (contextSpec) => client.models.Todo.list(contextSpec),
  });
  return data(
    {
      todos,
      error: errors?.map((e) => e.message).join(", "),
    },
    {
      headers: responseHeaders,
    }
  );
}

export default function Home({ loaderData }: Route.ComponentProps) {
  const { todos } = loaderData;
  return (
    <div className="flex flex-col gap-y-3 my-4 mx-2">
      <h1 className="text-2xl font-bold">Todo List</h1>
      <TodoList items={todos} />
      <Link to="/new">
        <button
          type="button"
          className="bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded"
        >
          Add Todo
        </button>
      </Link>
    </div>
  );
}

Example