HANAMU
@HANAMU (はなむ++)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Error: Objects are not valid as a React child (found: [object Promise]).を解決したい

解決したいこと

私は、TypeScript,React,Next.js,Firebase等を用いてTwitterのようなWebアプリを解決しています。
tailwind.css,MUI等も使用しています。
[id].tsxを使ったダイナミックルーティング機能で各アカウントページを実装しようとすると、エラーが出されてしまいます。解決方法を教えていただけると幸いです。

発生している問題・エラー

Error: Objects are not valid as a React child (found: [object Promise]).If you meant to render a collection of children, use an array instead.

該当するソースコード

/profile/index.tsx
import React, { useEffect, useState } from "react";
import {
  getProviders,
  getSession,
  GetSessionParams,
  useSession,
} from "next-auth/react";
import { db } from "../../firebase";
import {
  collection,
  query,
} from "@firebase/firestore";
import Menubar from "../../components/Menubar/Home";
import { onSnapshot, orderBy } from "firebase/firestore";
import Card from "../../components/profile/Card";

export default function Profile(account): JSX.Element {
  const { data: session } = useSession();
  const [posts, setPosts] = useState([]);

  useEffect(
    () =>
      onSnapshot(
        query(collection(db, "accounts"), orderBy("timestamp", "desc")),
        (snapshot: any) => {
          setPosts(snapshot.docs);
        }
      ),
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [db]
  );
  return (
    <div className="">
      <Menubar />
      <main className="profile-page">
        {posts.map((account: any) => (
          <Card
            key={account.id}
            id={account.id}
            account={account.data()}
            post={undefined}
          />
        ))}
      </main>
      {/* <Footer /> */}
    </div>
  );
}
export async function getServerSideProps(context: GetSessionParams) {
  const providers = await getProviders();
  const session = await getSession(context);

  return {
    props: {
      providers,
      session,
    },
  };
}

/components/Card.tsx
import * as React from "react";
import { useSession } from "next-auth/react";
import { useRouter } from "next/router";

export default  function RecipeReviewCard({ id, post, account }) {
  const { data: session } = useSession();
  const router = useRouter();
  return (
    <>
    <div onClick={() => router.push(`/profile/id=${account.id}`)}>
      <section className="relative block" style={{ height: "500px" }}>
        <div
          className="absolute top-0 w-full h-full bg-center bg-cover"
          style={{
            backgroundImage:
              "url('https://images.unsplash.com/photo-1499336315816-097655dcfbda?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2710&q=80')",
          }}
        >
          <span
            id="blackOverlay"
            className="w-full h-full absolute opacity-50 bg-black"
          ></span>
        </div>
      </section>
      <section className="relative py-16 bg-gray-300">
        <div className="relative flex flex-col min-w-0 break-words bg-white w-full mb-6 shadow-xl rounded-lg -mt-64">
          <div className="px-9">
            <div className="flex flex-wrap justify-center">
              <div className="w-full lg:w-3/12 px-4 lg:order-2 flex justify-center">
                <div className="">
                  {/* <Image
                    alt="..."
                    src={account?.userImg}
                    className="shadow-xl rounded-full h-auto align-middle border-none absolute -m-16 -ml-20 lg:-ml-16"
                    style={{ maxWidth: "150px" }}
                  /> */}
                </div>
              </div>
              <div className="w-full lg:w-4/12 px-4 lg:order-3 lg:text-right lg:self-center">
                <div className="py-6 px-3 mt-32 sm:mt-0">
                  <button
                    className="bg-pink-500 active:bg-pink-600 uppercase text-white font-bold hover:shadow-md shadow text-xs px-4 py-2 rounded outline-none focus:outline-none sm:mr-2 mb-1"
                    type="button"
                    style={{ transition: "all .15s ease" }}
                  >
                    プロフィールを設定する
                  </button>
                </div>
                <div className="w-full px-4 lg:order-1">
                  <div className="flex justify-center lg:py-4 py-8">
                    <div className="lg:mx-4 p-5 text-center">
                      <span className="text-xl font-bold block uppercase tracking-wide text-gray-700">
                        89
                        {/* アクティビティ数 */}
                      </span>
                      <span className="text-sm text-gray-500">投稿数</span>
                    </div>
                    <div className="lg:mx-4 p-5 text-center">
                      <span className="text-xl font-bold block uppercase tracking-wide text-gray-700">
                        89
                      </span>
                      <span className="text-sm text-gray-500">質問回答数</span>
                    </div>
                  </div>
                </div>
              </div>
              <div className="text-center mt-12">
                <h3 className="text-4xl font-semibold leading-normal  text-gray-800 mb-2">
                  {account?.username}
                  {/* 名前 */}
                </h3>
                <div className="text-sm leading-normal mt-0 mb-2 text-gray-500 font-bold uppercase">
                  {account?.class}/{account?.club}
                </div>
                <div className="text-sm leading-normal mt-0 mb-2 text-gray-500 font-bold uppercase">
                  {account?.comment}
                </div>
              </div>
            </div>
          </div>
        </div>
      </section>
    </div>
    </>
  );
}
/profile/[id].tsx
/* eslint-disable jsx-a11y/alt-text */
/* eslint-disable @next/next/no-img-element */
/* eslint-disable react/jsx-no-undef */
/* eslint-disable @next/next/no-img-element */
/* eslint-disable react/jsx-no-comment-textnodes */
import React, { useEffect, useRef, useState } from "react";
import {
  getProviders,
  getSession,
  GetSessionParams,
  useSession,
} from "next-auth/react";
import { useRouter } from "next/router";
import { storage } from "../../firebase";
import {
  addDoc,
  collection,
  doc,
  serverTimestamp,
  updateDoc,
  getDocs,
  getFirestore,
  query,
  where,
} from "@firebase/firestore";
import Menubar from "../../components/Menubar/Home";
import { onSnapshot, orderBy } from "firebase/firestore";
import Card from "../../components/profile/Card";

export default async function Profile({account}) {
  const { data: session } = useSession();
  const db = getFirestore() as any;
  const router = useRouter();
  const { id } = router.query;
  // const userRef = db.collection("accounts");
  // const snapshot = await userRef.get();
  // console.log(id)
  // console.log(userRef)
  // snapshot.forEach((doc) => {
  //   console.log(doc.id, "===", id);
  // });

  // const userRef : any = doc(db, "accounts");
  // const snapshot = await userRef.get();
  // console.log(userRef.id)
  // snapshot.forEach((doc) => {
  //   if(doc.id, "===", account.id){
  //     console.log(doc.id)
  //   }
  // });
  return (
    <div className="">
      <Menubar />
      {/* <main className="profile-page"> */}
      {/* <p>idは{id}です</p> */}
      <Card
        key={account.id}
        id={account.id}
        account={account.data()}
        post={undefined}
      />
      {/* </main> */}
    </div>
  );
}
export async function getServerSideProps(context: GetSessionParams) {
  const providers = await getProviders();
  const session = await getSession(context);

  return {
    props: {
      providers,
      session,
    },
  };
}

自分で試したこと

[id].tsxは念の為記載しましたが、おそらく関係ありません。ソースコードも適当に記述しています。実を言うと、このファイルreturnの中に必要最低限の<div>タグ等を書いただけでこのエラーが起こるのです。
もしかしたら/profile/index.tsxから/profile/[id].tsxに遷移する際に問題が起きているせいで、このエラーが起こっているのでは?と思っています。
検索をかけて自分が理解できる範囲で尽力しましたが、うまくいきません...どうかお助けください。

0

2Answer

不要なasyncがついており、戻り値がPromiseオブジェクトになってるためですかね

/profile/[id].tsx
- export default async function Profile({account}) {
+ export default function Profile({account}) { 
2Like

Comments

  1. @HANAMU

    Questioner

    はっ!?!?!?!?!エラー治りました!!!!
    助かりました。ありがとうございます!
  2. @HANAMU

    Questioner

    他の解決方法はありますでしょうか?
    今回は解決しましたが、`async`が必要な場合に備えたいです。
    追加で申し訳ありません。

今回は解決しましたが、asyncが必要な場合に備えたいです。

Componentはasyncな作業を直接行えません.
例えばfetchに時間がかかる場合は,useEffect内で匿名関数を使用し,stateで情報を更新します.

useEffect(() => {
  (async () => {
    /*Some async tasks*/
  })();
}, []);

getServerSidePropsで必要な作業を行えるなら,Component側が何かする必要は基本的にありません.

2Like

Comments

  1. @HANAMU

    Questioner

    今一度、非同期処理に関して学んでみます。本当にありがとうございます。

Your answer might help someone💌