90149


### 前提

現在ポートフォリオサイトを作成しています。  
<https://github.com/takoyan33/manga-kousatu.net>  
<https://mangakousatunet.vercel.app/>

### 実現したいこと

現在ポートフォリオで作成している  
このカード部分をコンポーネント化したいと考えています。  
<https://mangakousatunet.vercel.app/home>

データはFirestoreから取得しており、  
mapで表示しています。

![イメージ説明](https://ddjkaamml8q8x.cloudfront.net/questions/2022-07-22/c61f85da-4602-4720-9baa-f7ad210cc22a.png)

### 発生している問題・エラーメッセージ

ですが、ファイルを２つに分けて、cardpost.jsを作り、コンポーネント化しようとしたのですが、  
上手くコンポーネント化されずに、  
真っ白なカード部分が6個表示されているという状態です。  
原因がまだわかっていないのですが、記述ミスなどでしょうか。  
よろしくお願いします。

![イメージ説明](https://ddjkaamml8q8x.cloudfront.net/questions/2022-07-22/321cbd9e-aa46-4b7c-9ff7-967045450729.png)

### 該当のソースコード

[code]

    #Cardpost.jsx
    import省略
    
    export const Cardpost = (
      downloadURL,
      id,
      title,
      categori,
      netabare,
      displayname,
      context,
      email,
      photoURL,
      createtime
    ) => {
      let router = useRouter();
      const auth = getAuth();
      const user = auth.currentUser;
    
      return (
        <div>
          <Grid key={id} className="flex m-auto">
            <Card className="lg:w-full my-4">
              <p className="m-auto text-center">
                <Image
                  className="m-auto text-center max-w-sm"
                  height={300}
                  width={300}
                  src={downloadURL}
                />
              </p>
              <CardContent>
                <Typography gutterBottom component="div" className="w-3/5 text-xl ">
                  {title}
                </Typography>
                <Typography variant="body2" color="text.secondary">
                  {categori == "ONE PIECE" && (
                    <p className="bg-blue-500 p-2 inline-block text-white text-center">
                      {categori}
                    </p>
                  )}
                  {categori == "呪術廻戦" && (
                    <p className="bg-purple-500 p-2 inline-block text-white text-center">
                      {categori}
                    </p>
                  )}
                  {categori == "東京リベンジャーズ" && (
                    <p className="bg-rose-500 p-2 inline-block text-white text-center">
                      {categori}
                    </p>
                  )}
                  {categori == "キングダム" && (
                    <p className="bg-yellow-500 p-2 inline-block text-white text-center">
                      {categori}
                    </p>
                  )}
                  <br></br>
    
                  {netabare == "ネタバレ有" && (
                    <div>
                      <p className="bg-yellow-500 mt-2 p-1 inline-block text-white text-center">
                        {netabare}
                      </p>
                      <br></br>
                      <button
                        onClick={Opentext}
                        className="bg-yellow-500 mt-2 p-1 inline-block text-white text-center"
                      >
                        表示する
                      </button>
                      {opentext == true && <p className="">{context}</p>}
                    </div>
                  )}
    
                  {netabare == "ネタバレ無" && (
                    <p className="bg-blue-500 mt-2 p-1 inline-block text-white text-center">
                      {netabare}
                    </p>
                  )}
    
                  <br></br>
                  <div className="w-80 m-auto" style={styles}>
                    {netabare == "ネタバレ無" && <p className="">{context}</p>}
                  </div>
    
                  <br></br>
                  <Avatar alt="Remy Sharp" src={photoURL} />
                  <p>{displayname}</p>
                  <br></br>
                  {createtime}
                </Typography>
              </CardContent>
    
              {user.email == email && (
                <CardActions>
                  <Button
                    variant="outlined"
                    onClick={() =>
                      getID(data.id, data.name, data.age, data.title, data.context)
                    }
                  >
                    更新する
                  </Button>
                  <Button
                    variant="outlined"
                    onClick={() => deleteDocument(data.id)}
                  >
                    削除する
                  </Button>
                </CardActions>
              )}
            </Card>
          </Grid>
        </div>
      );
    };
    
    
    
[/code]

[code]

    #home.jsx
    import省略
    
    export default function Home() {
    const省略
    
      const auth = getAuth();
      const user = auth.currentUser;
      // console.log(user);
      useEffect(() => {
        let token = sessionStorage.getItem("Token");
    
        if (token) {
          getData();
        }
        if (!token) {
          router.push("/register");
        }
      }, []);
    
      const getData = async () => {
        await getDocs(databaseRef).then((response) => {
          setFiredata(
            response.docs.map((data) => {
              return { ...data.data(), id: data.id };
            })
          );
        });
      };
    
      const getID = (
        id,
        name,
        age,
        title,
        context,
        downloadURL,
        categori,
        cratetime,
        displayname,
        netabare,
        photoURL,
        userid
      ) => {
        setID(id);
        setContext(context);
        setTitle(title);
        setName(name);
        setAge(age);
        setDisplayName(displayname);
        setDownloadURL(downloadURL);
        setIsUpdate(true);
        setCategori(categori);
        setCreatetime(cratetime);
        setNetabare(netabare);
        setPhotoURL(photoURL);
        setUserid(userid);
        console.log(title);
      };
    
    記事の更新・削除の関数省略
     
      return (
        <div>
          <Head>
            <title>漫画考察.net/ホーム画面</title>
            <meta name="description" content="Generated by create next app" />
            <link rel="icon" href="/favicon.ico" />
          </Head>
          <MuiNavbar />
          <br></br>
          <div className="max-w-7xl m-auto">
            <div className="lg:text-right text-center">
              <Button variant="outlined" className="">
                <Link href="/post">新規投稿をする</Link>
              </Button>
              {/* <Search /> */}
            </div>
            <h2 className="m-5 my-12 text-center text-2xl font-semibold">
              投稿一覧
            </h2>
            <p className="text-1xl text-center">投稿数　{firedata.length}件</p>
    
            <Grid container spacing={1}>
              {firedata.map((data) => {
                return (
                  <Cardpost
                    key={data.id}
                    downloadURL={data.downloadURL}
                    title={data.title}
                    categori={data.categori}
                    context={data.context}
                    createtime={data.createtime}
                    displayname={data.displayname}
                    email={data.email}
                  />
          
            )}
          </div>
        </div>
      );
    }
    
    
    
[/code]

表示に成功した元ファイル

[code]

    import省略
    
    export default function Home() {
      const [ID, setID] = useState(null);
      const [title, setTitle] = useState("");
      const [context, setContext] = useState("");
      const [name, setName] = useState("");
      const [email, setEmail] = useState("");
      const [age, setAge] = useState(null);
      const [categori, setCategori] = useState("");
      const [firedata, setFiredata] = useState([]);
      const [createtime, setCreatetime] = useState("");
      const [isUpdate, setIsUpdate] = useState(false);
      const databaseRef = collection(database, "CRUD DATA");
      const [displayname, setDisplayName] = useState("");
      const [createObjectURL, setCreateObjectURL] = useState(null);
      const [downloadURL, setDownloadURL] = useState(null);
      const [image, setImage] = useState("");
      const [result, setResult] = useState("");
      const [photoURL, setPhotoURL] = useState("");
      const [userid, setUserid] = useState(null);
      const [netabare, setNetabare] = useState("");
      const [opentext, setOpentext] = useState(false);
      const styles = { whiteSpace: "pre-line" };
      let router = useRouter();
    
      const auth = getAuth();
      const user = auth.currentUser;
    
      useEffect(() => {
        let token = sessionStorage.getItem("Token");
    
        if (token) {
          getData();
        }
        if (!token) {
          router.push("/register");
        }
      }, []);
    
      const getData = async () => {
        await getDocs(databaseRef).then((response) => {
          setFiredata(
            response.docs.map((data) => {
              return { ...data.data(), id: data.id };
            })
          );
        });
      };
    
      const getID = (
        id,
        name,
        age,
        title,
        context,
        downloadURL,
        categori,
        cratetime,
        displayname,
        netabare,
        photoURL,
        userid
      ) => {
        setID(id);
        setContext(context);
        setTitle(title);
        setName(name);
        setAge(age);
        setDisplayName(displayname);
        setDownloadURL(downloadURL);
        setIsUpdate(true);
        setCategori(categori);
        setCreatetime(cratetime);
        setNetabare(netabare);
        setPhotoURL(photoURL);
        setUserid(userid);
        console.log(title);
      };
    
    
    
    
      return (
        <div>
          <Head>
            <title>漫画考察.net/ホーム画面</title>
            <meta name="description" content="Generated by create next app" />
            <link rel="icon" href="/favicon.ico" />
          </Head>
          <MuiNavbar />
          <br></br>
          <div className="max-w-7xl m-auto">
            <div className="lg:text-right text-center">
              <Button variant="outlined" className="">
                <Link href="/post">新規投稿をする</Link>
              </Button>
              {/* <Search /> */}
            </div>
            <h2 className="m-5 my-12 text-center text-2xl font-semibold">
              投稿一覧
            </h2>
            <p className="text-1xl text-center">投稿数　{firedata.length}件</p>
    
            <Grid container spacing={1}>
              {firedata.map((data) => {
                return (
                  <Grid key={data.id} className="flex m-auto">
                    <Card className="lg:w-full w-4/5 my-4 m-auto">
                      <p className="m-auto text-center ">
                        <Image
                          className="m-auto text-center max-w-sm"
                          height={250}
                          width={250}
                          src={data.downloadURL}
                        />
                      </p>
                      <CardContent>
                        <Typography
                          gutterBottom
                          component="div"
                          className="w-3/5 text-xl "
                        >
                          {data.title}
                        </Typography>
                        <Typography variant="body2" color="text.secondary">
                          {data.categori == "ONE PIECE" && (
                            <p className="bg-blue-500 p-2 inline-block text-white text-center">
                              {data.categori}
                            </p>
                          )}
                          {data.categori == "呪術廻戦" && (
                            <p className="bg-purple-500 p-2 inline-block text-white text-center">
                              {data.categori}
                            </p>
                          )}
                          {data.categori == "東京リベンジャーズ" && (
                            <p className="bg-rose-500 p-2 inline-block text-white text-center">
                              {data.categori}
                            </p>
                          )}
                          {data.categori == "キングダム" && (
                            <p className="bg-yellow-500 p-2 inline-block text-white text-center">
                              {data.categori}
                            </p>
                          )}
                          <br></br>
    
                          {data.netabare == "ネタバレ有" && (
                            <div>
                              <p className="bg-yellow-500 mt-2 p-1 inline-block text-white text-center">
                                {data.netabare}
                              </p>
                              <br></br>
                              <button
                                onClick={Opentext}
                                className="bg-yellow-500 mt-2 p-1 inline-block text-white text-center"
                              >
                                表示する
                              </button>
                              {opentext == true && (
                                <p className="">{data.context}</p>
                              )}
                            </div>
                          )}
    
                          {data.netabare == "ネタバレ無" && (
                            <p className="bg-blue-500 mt-2 p-1 inline-block text-white text-center">
                              {data.netabare}
                            </p>
                          )}
    
                          <br></br>
                          <div className="w-80 m-auto" style={styles}>
                            {data.netabare == "ネタバレ無" && (
                              <p className="">{data.context}</p>
                            )}
                          </div>
    
                          <br></br>
                          <Avatar alt="Remy Sharp" src={data.photoURL} />
                          <p>{data.displayname}</p>
                          <br></br>
                          {data.createtime}
                        </Typography>
                      </CardContent>
                    </Card>
                  </Grid>
                );
              })}
            </Grid>
    
            <br></br>
            <br></br>
            {isUpdate && (
              <Box
                component="form"
                sx={{
                  "& > :not(style)": { m: 1, width: "25ch" },
                }}
                noValidate
                autoComplete="off"
              >
                <TextField
                  id="outlined-basic"
                  label="タイトル（最大20文字)"
                  variant="outlined"
                  type="text"
                  value={title}
                  onChange={(event) => setTitle(event.target.value)}
                />
    
                <br></br>
    
                <TextField
                  label="内容(最大500文字）"
                  className="m-auto w-full"
                  id="filled-multiline-static"
                  multiline
                  rows={14}
                  type="text"
                  value={context}
                  onChange={(event) => setContext(event.target.value)}
                />
                <Button variant="outlined" onClick={updatefields}>
                  更新する
                </Button>
    
                <br></br>
                {/* <TextField
                  id="outlined-basic"
                  label="名前(最大20文字）"
                  variant="outlined"
                  type="text"
                  value={name}
                  onChange={(event) => setName(event.target.value)}
                /> */}
                <br></br>
              </Box>
            )}
          </div>
        </div>
      );
    }
    
    
[/code]


CC BY-SA 4.0
2022-07-22T10:22:20.560
90146
2022-07-23T17:39:06.800
52921
question
reactjs
Reactのコンポーネント化がされない


Reactのコンポーネント引数はPropsをObjectで受け取るのですが、質問に記載のコードではそうなっていないようです。`({})`で展開するのを想定しているのでしょう。

[code]

    export const Cardpost = ({
      downloadURL,
      id,
      title,
      categori,
      netabare,
      displayname,
      context,
      email,
      photoURL,
      createtime
    }) => {
    
[/code]

こういった型のミスはTypeScript等を用いると防げます。


CC BY-SA 4.0
2022-07-22T11:29:36.923
90149
2022-07-23T17:39:06.800
2022-07-23T17:39:06.800
2376
2376
90146
answer