examples: Update redis example with useOptimistic (#60596)

This commit is contained in:
Lee Robinson 2024-01-15 21:19:59 -06:00 committed by GitHub
parent ef1b66a518
commit b177ff6488
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 61 additions and 47 deletions

View file

@ -1,7 +1,7 @@
"use client";
import clsx from "clsx";
import { useOptimistic, useRef } from "react";
import { useOptimistic, useRef, useTransition } from "react";
import { saveFeature, upvote } from "./actions";
import { v4 as uuidv4 } from "uuid";
import { Feature } from "./types";
@ -23,22 +23,26 @@ function Item({
pending: boolean;
mutate: any;
}) {
const upvoteWithId = upvote.bind(null, feature);
let upvoteWithId = upvote.bind(null, feature);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
let [isPending, startTransition] = useTransition();
return (
<form
action={upvoteWithId}
onSubmit={async (event) => {
onSubmit={(event) => {
event.preventDefault();
mutate({
updatedFeature: {
...feature,
score: Number(feature.score) + 1,
},
pending: true,
});
await upvote(feature);
startTransition(async () => {
mutate({
updatedFeature: {
...feature,
score: Number(feature.score) + 1,
},
pending: true,
});
await upvote(feature);
});
}}
className={clsx(
"p-6 mx-8 flex items-center border-t border-l border-r",
@ -73,8 +77,8 @@ type FeatureState = {
};
export default function FeatureForm({ features }: { features: Feature[] }) {
const formRef = useRef<HTMLFormElement>(null);
const [state, mutate] = useOptimistic(
let formRef = useRef<HTMLFormElement>(null);
let [state, mutate] = useOptimistic(
{ features, pending: false },
function createReducer(state, newState: FeatureState) {
if (newState.newFeature) {
@ -112,6 +116,8 @@ export default function FeatureForm({ features }: { features: Feature[] }) {
score: "1",
};
let saveWithNewFeature = saveFeature.bind(null, featureStub);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
let [isPending, startTransition] = useTransition();
return (
<>
@ -120,7 +126,7 @@ export default function FeatureForm({ features }: { features: Feature[] }) {
className="relative my-8"
ref={formRef}
action={saveWithNewFeature}
onSubmit={async (event) => {
onSubmit={(event) => {
event.preventDefault();
let formData = new FormData(event.currentTarget);
let newFeature = {
@ -128,12 +134,15 @@ export default function FeatureForm({ features }: { features: Feature[] }) {
title: formData.get("feature") as string,
};
mutate({
newFeature,
pending: true,
});
formRef.current?.reset();
await saveFeature(newFeature, formData);
startTransition(async () => {
mutate({
newFeature,
pending: true,
});
await saveFeature(newFeature, formData);
});
}}
>
<input

View file

@ -30,27 +30,32 @@ function VercelLogo(props: React.SVGProps<SVGSVGElement>) {
}
async function getFeatures() {
let itemIds = await kv.zrange("items_by_score", 0, 100, {
rev: true,
});
try {
let itemIds = await kv.zrange("items_by_score", 0, 100, {
rev: true,
});
if (!itemIds.length) {
if (!itemIds.length) {
return [];
}
let multi = kv.multi();
itemIds.forEach((id) => {
multi.hgetall(`item:${id}`);
});
let items: Feature[] = await multi.exec();
return items.map((item) => {
return {
...item,
score: item.score,
created_at: item.created_at,
};
});
} catch (error) {
console.error(error);
return [];
}
let multi = kv.multi();
itemIds.forEach((id) => {
multi.hgetall(`item:${id}`);
});
let items: Feature[] = await multi.exec();
return items.map((item) => {
return {
...item,
score: item.score,
created_at: item.created_at,
};
});
}
export default async function Page() {

View file

@ -6,20 +6,20 @@
"start": "next start"
},
"dependencies": {
"@types/node": "20.10.3",
"@types/react": "18.2.42",
"@types/react-dom": "18.2.17",
"@types/node": "20.11.0",
"@types/react": "18.2.47",
"@types/react-dom": "18.2.18",
"@types/uuid": "9.0.7",
"@vercel/kv": "^1.0.0",
"@vercel/kv": "^1.0.1",
"autoprefixer": "10.4.16",
"clsx": "^2.0.0",
"geist": "^1.2.0",
"next": "canary",
"postcss": "^8.4.32",
"clsx": "^2.1.0",
"geist": "^1.2.1",
"next": "latest",
"postcss": "^8.4.33",
"react": "18.2.0",
"react-dom": "18.2.0",
"tailwindcss": "3.3.6",
"typescript": "5.3.2",
"tailwindcss": "3.4.1",
"typescript": "5.3.3",
"uuid": "^9.0.1"
}
}