Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate useTransition Hook for Optimized State Transitions #157

Merged
merged 10 commits into from
Dec 31, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions packages/frontend/src/components/ButtonSpinner.tsx
Original file line number Diff line number Diff line change
@@ -2,14 +2,7 @@ import React from "react";
import { Spinner } from "react-bootstrap";

const ButtonSpinner = () => (
<Spinner
as="span"
animation="border"
size="sm"
role="status"
aria-hidden="true"
className="mr-1"
/>
<Spinner as="span" animation="border" size="sm" role="status" aria-hidden="true" className="mr-1" />
);

export { ButtonSpinner };
5 changes: 1 addition & 4 deletions packages/frontend/src/components/PageContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import React from "react";
import { Card } from "react-bootstrap";

const PageContainer = (props: {
header: React.ReactNode;
children: React.ReactNode;
}) => (
const PageContainer = (props: { header: React.ReactNode; children: React.ReactNode }) => (
<Card>
<Card.Header>{props.header}</Card.Header>
<Card.Body>{props.children}</Card.Body>
41 changes: 19 additions & 22 deletions packages/frontend/src/content/CreateNote.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, FormEvent } from "react";
import React, { useState, FormEvent, useTransition } from "react";
import { Form, Button, Alert } from "react-bootstrap";
import { navigate, RouteComponentProps } from "@reach/router";
import { GATEWAY_URL } from "../config";
@@ -10,7 +10,7 @@ import { PlayAudioButton } from "./PlayAudioButton";
const MAX_FILE_SIZE = 2000000;

const CreateNote = (props: RouteComponentProps) => {
const [isLoading, setIsLoading] = useState(false);
const [isPending, startTransition] = useTransition();
const [errorMsg, setErrorMsg] = useState("");
const [noteContent, setNoteContent] = useState("");
const [file, setFile] = useState();
@@ -26,24 +26,21 @@ const CreateNote = (props: RouteComponentProps) => {
setErrorMsg(`File can't be bigger than ${MAX_FILE_SIZE / 1000000} MB`);
return;
}
startTransition(async () => {
const createNoteURL = `${GATEWAY_URL}notes`;

setIsLoading(true);

const createNoteURL = `${GATEWAY_URL}notes`;

try {
// @ts-ignore Argument of type 'undefined' is not assignable to parameter of type 'File'
const attachment = file ? await putObject(file) : undefined;
await fetch(createNoteURL, {
method: "POST",
body: JSON.stringify({ attachment, content: noteContent }),
});
navigate("/");
} catch (error) {
setErrorMsg(`${error.toString()} - ${createNoteURL} - ${noteContent}`);
} finally {
setIsLoading(false);
}
try {
// @ts-ignore Argument of type 'undefined' is not assignable to parameter of type 'File'
const attachment = file ? await putObject(file) : undefined;
await fetch(createNoteURL, {
method: "POST",
body: JSON.stringify({ attachment, content: noteContent }),
});
navigate("/");
} catch (error) {
setErrorMsg(`${error.toString()} - ${createNoteURL} - ${noteContent}`);
}
});
};

const noteContentAdditionalProps = isRecording || isPlaying ? { disabled: true, value: noteContent } : {};
@@ -90,9 +87,9 @@ const CreateNote = (props: RouteComponentProps) => {
type="file"
/>
</Form.Group>
<Button type="submit" disabled={!noteContent || isLoading} block>
{isLoading ? <ButtonSpinner /> : ""}
{isLoading ? "Creating..." : "Create"}
<Button type="submit" disabled={!noteContent || isPending} block>
{isPending ? <ButtonSpinner /> : ""}
{isPending ? "Creating..." : "Create"}
</Button>
</form>
</PageContainer>
34 changes: 16 additions & 18 deletions packages/frontend/src/content/DeleteNoteButton.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { useState, useTransition } from "react";
import { Button, Alert } from "react-bootstrap";
import { GATEWAY_URL } from "../config";
import { navigate } from "@reach/router";
@@ -7,28 +7,26 @@ import { ButtonSpinner } from "../components";

const DeleteNoteButton = (props: { noteId: string; attachment?: string }) => {
const { noteId, attachment } = props;
const [isDeleting, setIsDeleting] = useState(false);
const [isDeleting, startTransition] = useTransition();
const [errorMsg, setErrorMsg] = useState("");

const handleDelete = async (event: any) => {
const handleDelete = (event: React.MouseEvent<HTMLButtonElement>) => {
event.preventDefault();
setIsDeleting(true);
startTransition(async () => {
const deleteNoteURL = `${GATEWAY_URL}notes/${noteId}`;

const deleteNoteURL = `${GATEWAY_URL}notes/${noteId}`;

try {
if (attachment) {
await deleteObject(attachment);
try {
if (attachment) {
await deleteObject(attachment);
}
await fetch(deleteNoteURL, {
method: "DELETE",
});
navigate("/");
} catch (error) {
setErrorMsg(`${error.toString()} - ${deleteNoteURL} - ${noteId}`);
}
await fetch(deleteNoteURL, {
method: "DELETE",
});
navigate("/");
} catch (error) {
setErrorMsg(`${error.toString()} - ${deleteNoteURL} - ${noteId}`);
} finally {
setIsDeleting(false);
}
});
};

return (
31 changes: 15 additions & 16 deletions packages/frontend/src/content/ListNotes.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, useEffect } from "react";
import React, { useState, useTransition, useEffect } from "react";
import { Link, RouteComponentProps } from "@reach/router";
import { GATEWAY_URL } from "../config";
import { Card, Alert, CardColumns, Button } from "react-bootstrap";
@@ -11,24 +11,23 @@ interface Note {
}

const ListNotes = (props: RouteComponentProps) => {
const [isLoading, setIsLoading] = useState(true);
const [isPending, startTransition] = useTransition();
const [errorMsg, setErrorMsg] = useState("");
const [notes, setNotes] = useState([]);
const [notes, setNotes] = useState<Note[]>([]);

useEffect(() => {
const fetchNotes = async () => {
setIsLoading(true);
const fetchURL = `${GATEWAY_URL}notes`;
const fetchNotes = () => {
startTransition(async () => {
const fetchURL = `${GATEWAY_URL}notes`;

try {
const response = await fetch(fetchURL);
const data = await response.json();
setNotes(data);
} catch (error) {
setErrorMsg(`${error.toString()} - ${fetchURL}`);
} finally {
setIsLoading(false);
}
try {
const response = await fetch(fetchURL);
const data = await response.json();
setNotes(data);
} catch (error) {
setErrorMsg(`${error.toString()} - ${fetchURL}`);
}
});
};
fetchNotes();
}, []);
@@ -65,7 +64,7 @@ const ListNotes = (props: RouteComponentProps) => {
return (
<PageContainer header={<div>Your Notes</div>}>
{errorMsg && <Alert variant="danger">{errorMsg}</Alert>}
{isLoading ? (
{isPending ? (
<Loading />
) : (
<div>
40 changes: 19 additions & 21 deletions packages/frontend/src/content/SaveNoteButton.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,38 @@
import React, { useState } from "react";
import React, { useState, useTransition } from "react";
import { Button, Alert } from "react-bootstrap";
import { GATEWAY_URL } from "../config";
import { navigate } from "@reach/router";
import { ButtonSpinner } from "../components";

const SaveNoteButton = (props: { noteId: string; noteContent: string }) => {
const [isSaving, setIsSaving] = useState(false);
const [isPending, startTransition] = useTransition();
const [errorMsg, setErrorMsg] = useState("");

const handleSave = async (event: any) => {
event.preventDefault();
setIsSaving(true);
startTransition(async () => {
const { noteId, noteContent } = props;
const updateNoteURL = `${GATEWAY_URL}notes/${noteId}`;

const { noteId, noteContent } = props;
const updateNoteURL = `${GATEWAY_URL}notes/${noteId}`;

try {
await fetch(updateNoteURL, {
method: "PUT",
body: JSON.stringify({ content: noteContent }),
});
navigate("/");
} catch (error) {
console.log(error);
setErrorMsg(`${error.toString()} - ${updateNoteURL} - ${noteContent}`);
} finally {
setIsSaving(false);
}
try {
await fetch(updateNoteURL, {
method: "PUT",
body: JSON.stringify({ content: noteContent }),
});
navigate("/");
} catch (error) {
console.log(error);
setErrorMsg(`${error.toString()} - ${updateNoteURL} - ${noteContent}`);
}
});
};

return (
<>
{errorMsg && <Alert variant="danger">{errorMsg}</Alert>}
<Button disabled={isSaving} onClick={handleSave} block>
{isSaving ? <ButtonSpinner /> : ""}
{isSaving ? "Saving..." : "Save"}
<Button disabled={isPending} onClick={handleSave} block>
{isPending ? <ButtonSpinner /> : ""}
{isPending ? "Saving..." : "Save"}
</Button>
</>
);
41 changes: 20 additions & 21 deletions packages/frontend/src/content/ShowNote.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, useEffect } from "react";
import React, { useState, useEffect, useTransition } from "react";
import { RouteComponentProps, navigate } from "@reach/router";
import { Form, Card } from "react-bootstrap";
import { GATEWAY_URL } from "../config";
@@ -8,37 +8,36 @@ import { HomeButton, Loading, PageContainer } from "../components";

const ShowNote = (props: RouteComponentProps<{ noteId: string }>) => {
const { noteId } = props;
const [isLoading, setIsLoading] = useState(true);
const [isPending, startTransition] = useTransition();
const [noteContent, setNoteContent] = useState("");
const [attachment, setAttachment] = useState("");
const [attachmentURL, setAttachmentURL] = useState("");


useEffect(() => {
const fetchNote = async (noteId: string) => {
setIsLoading(true);
const fetchURL = `${GATEWAY_URL}notes/${noteId}`;
if (noteId) {
startTransition(async () => {
const fetchURL = `${GATEWAY_URL}notes/${noteId}`;

try {
const response = await fetch(fetchURL);
const data = await response.json();
setNoteContent(data.content);
if (data.attachment) {
setAttachment(data.attachment);
setAttachmentURL(await getObjectUrl(data.attachment));
try {
const response = await fetch(fetchURL);
const data = await response.json();
setNoteContent(data.content);
if (data.attachment) {
setAttachment(data.attachment);
setAttachmentURL(await getObjectUrl(data.attachment));
}
} catch (error) {
// Navigate to 404 page, as noteId probably not present
navigate("/404");
}
} catch (error) {
// Navigate to 404 page, as noteId probably not present
navigate("/404");
} finally {
setIsLoading(false);
}
};
fetchNote(noteId || "");
});
}
}, [noteId]);

return (
<PageContainer header={<HomeButton />}>
{isLoading ? (
{isPending ? (
<Loading />
) : (
<form>