0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[React] 「投稿がありません」コメント描画のロジックでハマった話

Last updated at Posted at 2020-05-18

前提

  • React.js
  • データベースはFirestore(Firebaseのcloud datebase)
  • 投稿記事のvalueにFirebase Authenticationのuidをアップして連携可能にしている

ハマったこと

現在SNSアプリの仕組みを実装している中、
投稿がない場合、「投稿がありません」と1文を出そうと思っていたところ、
下記コードのように配列でループで表示いるため、リスト分「投稿がありません」と表示されてしまう。
このままだとログイン(auth)投稿者以外の記事分、表示されてしまう。

いや〜マジで困った。

やりたいこと

authユーザーの記事のみ表示 ← これのみならすでに可能
            かつ
もし記事がなかったら「投稿がありません」の1文を1個のみ表示

問題の箇所抽出
{list.map(item => (
    <React.Fragment key={item.docId + String(new Date())}>
        {authId === item.authId ? (
            <div>{item.msg}</div>
        ) : (
            {/* ループの中に入っているためリスト分表示されてしまう */}
            <div>
                投稿がありません
            </div>
        )}
    </React.Fragment>
))}

解決方法

以下の方法で無事解決できました。

うまくいった方法

処理を分けて書けばよかった

js側・・・投稿記事を抽出するロジックを書いて結果を出しておく

  • 事前に配列をfilterして、表示すべき分だけに絞り込んでおく
  • 配列のlengthを取得

jsx側・・・表示のみにする

  • 1つもなければ(lengthが0なら)「ありませんでした」メッセージを表示
  • filter後の配列をmapして出力

解決に至った記事

【JavaScript入門】filterで配列のデータを抽出する方法

解決箇所抽出
// js側で抽出
    // auth userの投稿記事のみ抽出
    const result = list.filter((e) => {
        return e.authId === authId;
    });
    console.log(result);
    const length = result.length;
    console.log(length);

{/* jsx側で表示 */}
<div className="post-list user-post-list">
{length !== 0 ? (
    <React.Fragment>
        {result.map(item => (
            <div key={item.docId + String(new Date())}>
                <div className="auth-inner-post-list">
                    <div className="auth-inner-post-text">
                        <div className="post-msg">{item.msg}</div>
                        <span className="delete"  onClick={() => handleDelete(item.docId)}>&gt; Delete...</span>
                    </div>
                </div>
            </div>
        ))}
    </React.Fragment>
) : (
    <div className="no-user-posts">まだ記事が投稿されていません</div>
)}
</div>
コード全文
import React from 'react';
import { Link } from 'react-router-dom';
import firebase, { db } from '../../Firebase';
import SignOut from '../FirebaseAuthHook/SignOut';
import { useCollectionData } from "react-firebase-hooks/firestore";
import BackTopIcon from '../../assets/img/backtop.png';
import UserIcon from '../../assets/img/user.png';
import styled from 'styled-components';

const BackTopStyle = styled.img`
  width: 50px;
  top: 25px;
  left: 25px;
  position: fixed;
  zIndex: 11,
`;

const Index = () => {
    // Firebese Auth uid, email取得
    const user = firebase.auth().currentUser;
    let authId;
    let name;
    let photoURL;
    if (user !== null) {
        user.providerData.forEach(() => {
            authId = user.uid;
            name = user.displayName;
            photoURL = user.photoURL;
        });
    }

    // Render
    const [ list, loading, error ] = useCollectionData(db.collection('posts').orderBy('createdAt', 'desc'), { idField: 'docId' });
    if (loading) return <div>Loading...</div>;
    if (error) return <div>Error...</div>;
     
    // auth userの投稿記事のみ抽出
    const result = list.filter((e) => {
        return e.authId === authId;
    });
    console.log(result);
    const length = result.length;
    console.log(length);
    

    // Delete
    const handleDelete = (uid) => {
        if (window.confirm('削除しますか?')) {
            db.collection('posts').doc(uid).delete();
        }
    }
        
    return(
        <React.Fragment>
            <SignOut />
            <Link to="/"><BackTopStyle src={ BackTopIcon } alt="Topに戻る"/></Link>

            <div className="user-wrapper">
                <div className="user">
                    {photoURL ? (
                        <img src={ photoURL } className="auth-user-icon" alt="User Thumbnail" />
                    ) : (
                        <img src={ UserIcon } className="auth-user-icon" alt="Firebase Thumbnail" />
                    )}
                    <div className="user-datail">
                        {name ? (
                            <div className="user-name">{name}</div>
                        ) : (
                            <div className="user-name">Firebaseユーザー</div>
                        )}
                    </div>
                </div>

                <div className="post-list user-post-list">
                {length !== 0 ? (
                    <React.Fragment>
                        {result.map(item => (
                            <div key={item.docId + String(new Date())}>
                                <div className="auth-inner-post-list">
                                    <div className="auth-inner-post-text">
                                        <div className="post-msg">{item.msg}</div>
                                        <span className="delete"  onClick={() => handleDelete(item.docId)}>&gt; Delete...</span>
                                    </div>
                                </div>
                            </div>
                        ))}
                    </React.Fragment>
                ) : (
                    <div className="no-user-posts">まだ記事が投稿されていません</div>
                )}
                </div>
            </div>
        </React.Fragment>
    );
}

export default Index;

今回のことで学んだこと

分かってみると実に単純なことでした。
今後はView側で全て処理しようとせずにJS側でロジックを組むクセづけが必要だと感じました。
またフレームワークを使っていても素のJSのメソッドがかなり重要だと実感しています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?