LoginSignup
Akinko0915
@Akinko0915 (暁 中原)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

Server Action の戻り値を取得する方法

App Routerと Server Actionを使えるようになりたいです。
Server Action ができたおかげで、同じファイルにサーバー側の処理とクライアント側の処理を書けるようになったと理解しています。

素人にもかかわらず、Server Action にいきなり取り組んでしまったが、後には戻れずって感じで調べながら行っています…
間違った解釈も含めて、何かしら指摘・回答していただけたら幸いです。

解決したいこと

formにインプットされたデータを Server Action で処理して、処理された結果をHome 関数内で取得したい。そして、その結果を指定した箇所に、ブラウザを再読み込みさせず表示させたい。

例)
Nextjsで、入力した日本語をやさしい日本語に変換させるアプリを作っています。左の箱に変換したい日本語、右の箱に変換された日本語を表示させます。

まだ変換する処理までいっておらず、現時点では入力されたテキストを大文字にする処理を書いています。

発生している問題

Home function 下で、ResultBoxのコンポーネントにresultTextの変数を渡すために、resultの変数をserver actions から取得したい

全体のコード (app/page.tsx)

import { revalidatePath } from "next/cache";
import { ResultBox } from "./Result";

async function toUppercase(text: string): Promise<string> {
  // Process the text using the OpenAI API and return the result
  // ...
  const processedText = text.toUpperCase();
  return processedText;
}

async function convert(formData: FormData) {
  "use server";
  const text = formData.get("inputText") as string;
  if (!text) {
    return { error: "Please enter some text to process." };
  }

  console.log("Processing text:", text);
  // Process the text using the OpenAI API and return the result
  const result = await toUppercase(text);
  revalidatePath("/");
  return { result };
}

export default function Home() {
  const resultText = convert.result?.result;

  return (
    <main className="flex min-h-screen flex-col items-center justify-center p-24">
      <div className="relative flex flex-col place-items-center before:absolute">
        <h1 className="mb-6 text-3xl font-bold">やさしい日本語変換</h1>
        <p className="mb-6 text-lg font-bold">
          むずかしい日本語を、わかりやすく・よみやすい、やさしい日本語に変換します。
        </p>
        <div className="flex items-start">
          <form action={convert} className="flex flex-col items-center mr-4">
            <textarea
              name="inputText"
              className="mb-4 rounded-md"
              placeholder="日本語を入力してください"
            ></textarea>
            <button
              type="submit"
              className="button rounded-lg border border-transparent px-5 py-4"
            >
              <h2 className="text-xl font-semibold">へんかん!</h2>
            </button>
          </form>
          <ResultBox result={resultText} />
        </div>
      </div>
    </main>
  );
}

該当箇所

const resultText = convert.result?.result;

自分で試したこと

結果をどのようにして Home 関数で取得するかは、力足らずで分からりませんでしたが、取得した後にどのようにして表示させる方法は、以下のサイトで分かったのかなと思っています。

https://azukiazusa.dev/blog/nextjs-server-action/
revalidatePathまたはuseTransitionを使用したいと思っていますが、そもそも処理された変数を取得し、コンポーネントに渡さなければできないことに気付きました。

0

1Answer

下記のようなコードを変換すると問題を解決するかな?

"use client";

import { useState } from "react";
import ResultBox from "./components/ResultBox";
import toUppercase from "./actions/toUppercase";

interface CommonActionsReturn {
  success: boolean;
  message: string;
  data: string;
}

export default function Home() {
  const convert = async (formData : FormData) => {
    const text : FormDataEntryValue | null = formData.get("inputText")

    const result : CommonActionsReturn = await toUppercase(text);

    if(result.success) {
      setResultText(result.data);
    }else{
      // エラー処理
    }
  }

  const [resultText, setResultText] = useState<string>('');

  return (
    <main className="flex min-h-screen flex-col items-center justify-center p-24">
      <div className="relative flex flex-col place-items-center before:absolute">
        <h1 className="mb-6 text-3xl font-bold">やさしい日本語変換</h1>
        <p className="mb-6 text-lg font-bold">
          むずかしい日本語を、わかりやすく・よみやすい、やさしい日本語に変換します。
        </p>
        <div className="flex items-start">
          <form action={convert} className="flex flex-col items-center mr-4">
            <textarea
              name="inputText"
              className="mb-4 rounded-md"
              placeholder="日本語を入力してください"
            ></textarea>
            <button
              type="submit"
              className="button rounded-lg border border-transparent px-5 py-4"
            >
              <h2 className="text-xl font-semibold">へんかん!</h2>
            </button>
          </form>
          <ResultBox result={resultText} />
        </div>
      </div>
    </main>
  );
}
// toUppercase.ts
"use server";

interface CommonActionsReturn {
    success: boolean;
    message: string;
    data: string;
}

export default async function toUppercase (text : FormDataEntryValue | null) : Promise<CommonActionsReturn> {
    // 実際の処理
    // Process the text using the OpenAI API and return the result
    if(!text) return { success : false, message : 'Please enter some text to process.', data : '' };

    const _text : string = (text as string).toUpperCase();

    return { success : true, message : 'success', data: _text };
}
0

Comments

  1. @Akinko0915

    Questioner

    返信が遅れてすみません、すごい、、、できました。
    何が違っていたのかこれから自分でも分析してみます。もし何かここを大きく変えた箇所や意識した点などあれば、覚えている範囲でよいのでおしえていただけるとうれしいです!!

Your answer might help someone💌