herohoroブログ

記事ページにDBの情報を表示させる | useEffect・enableLink_Blog learn05



🔄   2023-03-14

前回記事ページを作成しました。

NotionAPIで取得したslugの値で記事リンクを作成する | getStaticPathとDynamic routesが便利だ_Blog learn04

今こんな感じ。

image block

https://codesandbox.io/embed/slug-read-router-page-xiu-zheng-ji-ykipsk?fontsize=14&hidenavigation=1&theme=dark

記事ページに表示させている「Post: notion-api_make-blog」はNotionDBのslug列で記入している文字。

const RenderPost = (post) => {
  const router = useRouter();
  const { slug } = router.query;

  return (
    <div className={styles.container}>
      <div className={styles.mainContent}>
        <p>Post: {slug}</p>  👉  これ         
      </div>
    </div>
  );
};

export default RenderPost;
src/pages/blog/[slug].tsx

記事一覧ページ(blog/index.tsx)で使うような

componentでペトペト貼って使えるようにするぞ......!!!!!

っていうのが今回のテーマです\(^o^)/

const RenderPosts = ({ posts = [] }) => {
  return (
    <div className={styles.container}>
      <div className={styles.mainContent}>
        <p>***main-content***</p>
        <h2>BlogList page</h2>
        <br />
        {""}
        <section>
          <div>
            {posts.map((post) => {
              return (
                <div key={post.Slug}>
                  <PostDate post={post} />   👉    これ使いたいなー          
                  <PostTitle post={post} />  👉   これもあったらいいよなー
                  <PostExcerpt post={post} />   👉  これは本文にはいらないかなーーー
                </div>
              );
            })}
          </div>
/// 以下省略......
src/pages/blog/index.tsx

image block

普通にペトっとしてみたら.....失敗

いつものようにcomponentを使いたい場所に貼ってみました。

import { PostDate } from "../../components/blog-parts";
//省略

const RenderPost = (post) => {
  const router = useRouter();
  const { slug } = router.query;

  return (
    <div className={styles.container}>
      <div className={styles.mainContent}>
        <p>Post: {slug}</p>
        <PostDate post={post} />  👉 ペトっ
      </div>
    </div>
  );
};

export default RenderPost;
src/pages/blog/[slug].tsx

image block

日付がNanNanNanです.....。

なんでしょう......(´゚д゚`)


以下、useEffectが原因だと思い込んで説明してしまっているので、

useEffectの中のifがあってredirectが設定されていないから条件を満たしていない

ということを頭の隅に置きながら読み進めていってください....(^_^;)

結果を先に知りたい方は、「原因を振り返ると....」へ飛んでくださいm(_ _)m


本家のコードを確認

見慣れないコードを発見。

image block
src/pages/blog/[slug].tsx

useEffectって???

useEffect は何をやっているのか?
レンダー後に何かの処理をしないといけない、ということを React に伝えます。
React はあなたが渡した関数を覚えており(これを「副作用(関数)」と呼ぶこととします)、DOM の更新の後にそれを呼び出します。
useEffect は毎回のレンダー後に呼ばれるのか?
「マウント」と「更新」という観点で考えるのではなく、「レンダーの後」に副作用は起こる、というように考える方が簡単かもしれません。
React は、副作用が実行される時点では DOM が正しく更新され終わっていることを保証します。

副作用フックの利用法/React 公式Doc

ちょっと公式Docは私には難解だったので、

こちらの記事がしっくりと理解できました....😅

【React Hooks】useEffectの基本的な動きを理解して使いこなそう

useEffectは、関数コンポーネント内で副作用(side-effect)を実行するためのHookです。
副作用とは、関数コンポーネントの出力(レンダリング)に関係ない処理のことです。
つまり、useEffectを用いることでレンダリングと副作用を切り離すことが可能になります。

useEffect(callback[, dependencies]);
useEffectの構文

callback関数について調べつつ構文を解釈すると.....

  • 第一引数:処理して欲しい内容
  • 第二引数:お伺いする相手

っていうイメージ。

Reactがやっと出てきました。

React Hookってよく耳にしますが、その一味なようです。

実装(仮)

実行させるタイミングを指定できるのがuseEffectの特徴。

  • いつ実行させる????
    • 👉 router・redirect・postの変更があった時
  • 何して欲しいの??
    • 👉 redirectしてもpostデータが存在していなかったらrouterをredirectに書き換えて欲しいの。
    • 👉それ以外は何もしないでね。

import { useEffect } from "react";
//省略

const RenderPost = ({ post, redirect }) => {

  const router = useRouter();
  const { slug } = router.query;
/// ▼ ここから....
  useEffect(() => {
    if (redirect && !post) {
      router.replace(redirect);
    }
  }, [router, redirect, post]);
////  ▲ ここまでの部分
return (
    <div className={styles.container}>
      <div className={styles.mainContent}>
        <p>Post: {slug}</p>
        <PostDate post={post} />
      </div>
    </div>
  );
};

export default RenderPost;
src/pages/blog/[slug].tsx

日付が表示されたーーー\(^o^)/

image block

▼ 実はuseEffectによって表示されている...ということでもなかった😵

結局useEffectはpostが無かった時に処理するためのものだ.....

****  追加しました 2022/05/18 ******

image block

🤔
どういうことだ???(もう一度ツイート見返そっと....)

後日もう一度作り直してみて、NaNNanNaNの原因を調べるマスーーーー。(´・ω・`)

単純な記述ミスかもしれない.....。

NaNNaNNaNはいったい何なんだ~~~~~~~~


*** 追加しました 2022/05/21 ***

Blog learn04をForkして作り直してみると....

image block

NaN-aN-aNが再び出現!!!!


....全然分からない.....m(_ _)m


みつけたーーーーーー(´゚д゚`)

image block

原因を振り返ると......

useEffectを追加する時にredirectを引数として加える際

{ }でくくったことでNaNが直った....ってことが分かりました。

やはりアルパカ先生のご指摘どおり、

useEffectの不足によるものではなく、別の理由(単に文法ミス)でした(;・∀・)

ひょいなことからuseEffectをゴリゴリ調べることとなりましたが、

これはこれで勉強になりました\(^o^)/www

import { useEffect } from "react";
//省略

const RenderPost = ({ post }) => {

  const router = useRouter();
  const { slug } = router.query;

return (
    <div className={styles.container}>
      <div className={styles.mainContent}>
        <p>Post: {slug}</p>
        <PostDate post={post} />
      </div>
    </div>
  );
};

export default RenderPost;
src/pages/blog/[slug].tsx 文法ミス_修正

Titleも表示させる

import { PostDate,PostTitle } from "../../components/blog-parts";
//省略

const RenderPost = ({ post }) => {

//省略
return (
    <div className={styles.container}>
      <div className={styles.mainContent}>
        <p>Post: {slug}</p>
        <PostDate post={post} />
				<PostTitle post={post} />    👉  追加
      </div>
    </div>
  );
};

export default RenderPost;
src/pages/blog/[slug].tsx

タイトルが表示された\(^o^)/

image block

🤔
でもリンク埋め込みのままになってる.....

タイトルのリンク埋め込みを使い分ける

本家のコードを確認すると、

PostTitleのcomponentにこんな記述が(´゚д゚`)

image block
easy-notion-blog src/src/components/blog-parts.tsx

三項演算子で、

  • enableLinkがあったら....
    • タイトルにリンク埋め込みをする
  • enableLinkがなかったら....
    • タイトルのみ

デフォルトでenableLink = true になっているので、

不要な時にfalse にしてあげれば良さそう★

componentにenableLinkの三項演算子を追加してあげて.....

export const PostTitle = ({ post, enableLink = true }) => {
  const postTitle = post.Title ? post.Title : "";
  return (
    <h3>
      {enableLink ? (
        <Link href="/blog/[slug]" as={getBlogLink(post.Slug)} passHref>
          <a>{postTitle}</a>
        </Link>
      ) : (
        postTitle
      )}
    </h3>
  );
};
src/components/blog-parts.tsx  PostTitle修正

記事ページのタイトルはenableLinkを使わないように設定する。

//省略

const RenderPost = ({ post }) => {

//省略
return (
    <div className={styles.container}>
      <div className={styles.mainContent}>
        <p>Post: {slug}</p>
        <PostDate post={post} />
				<PostTitle post={post} enableLink={false}/>    👉  追加
      </div>
    </div>
  );
};

export default RenderPost;
src/pages/blog/[slug].tsx enableLink追加

リンクの埋め込みのないタイトルになった\(^o^)/

image block

まとめ

記事ページ([slug].tsx)にNotionDBの情報を2つ(Date・Title)を表示させるには.....

  1. useEffectを使って実行するタイミングを設定する...のは今回関係無かった
    1. 👉本来はいつものように貼り付ければNaNにならずに表示されるはず.....
    2. 🙌 RenderPostの引数(post)を{ }でくくることで解決
  2. 使いたいcomponent(PostDate・PostTitle)を追記する
  3. enableLinkを使ってタイトルのリンク埋め込みを使い分ける

今回使用したcode sandboxはこちら

https://codesandbox.io/embed/slug-read-router-page-colum-mergeyu-ding-zz22j8?fontsize=14&hidenavigation=1&theme=dark

useEffectがあることで、

記事ページごとに表示させる情報の切り替えができている

っていうことが分かりました\(^o^)/

次回はNotionの本文テキストを表示させちゃいます🔥


enableLinkのような使い方って、

カスタマイズする時に役立ちそう.....。

componentにあった三項演算子も勉強になるなーー🤨

私の場合で言えば、

記事一覧ページでは2カラムサイズの表示にしたいけど、

記事ページでは1つの記事だけしかないから幅をいっぱい使って表示させたい。

今の段階では2パターンでわざわざcomponentを用意して、

ガッチャガチャになってるけど、

今日学べた使い方を取り入れればだいぶ清潔になるのかな〜

なんてことを思いました(´;ω;`)

まだまだやることたくさんアリマス.....な(´゚д゚`)

Twitterでは更新のお知らせを随時行っています

興味ある方はLet'sフォロー★

▼ この記事に興味があったら同じタグから関連記事をのぞいてみてね

Buy Me A Coffee

新着記事を通知したい??


RSSリーダーにatomのリンクを登録すると通知が行くよ🐌

https://herohoro.com/atom

やってみてね(*´ω`*)(*´ω`*)

Twitter Timeline


フォロー大歓迎\(^o^)/