質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Redux

Reduxは、JavaScriptアプリケーションの状態を管理するためのオープンソースライブラリです。ReactやAngularで一般的にユーザーインターフェイスの構築に利用されます。

SPA(Single-page Application)

SPA(Single-page Application)は、単一のWebページのみでコンテンツの切り替えができるWebアプリケーションもしくはWebサイトです。ブラウザでのページ遷移がないため、デスクトップアプリケーションのようなUXを提供します。

Cloud Firestore

Cloud Firestore は、自動スケーリングと高性能を実現し、アプリケーション開発を簡素化するように構築された NoSQLドキュメントデータベースです。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

1回答

2465閲覧

ReactのSPAにおける、サーバーからのデータ取得タイミング

tacro

総合スコア23

Redux

Reduxは、JavaScriptアプリケーションの状態を管理するためのオープンソースライブラリです。ReactやAngularで一般的にユーザーインターフェイスの構築に利用されます。

SPA(Single-page Application)

SPA(Single-page Application)は、単一のWebページのみでコンテンツの切り替えができるWebアプリケーションもしくはWebサイトです。ブラウザでのページ遷移がないため、デスクトップアプリケーションのようなUXを提供します。

Cloud Firestore

Cloud Firestore は、自動スケーリングと高性能を実現し、アプリケーション開発を簡素化するように構築された NoSQLドキュメントデータベースです。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

0クリップ

投稿2020/07/13 05:03

編集2020/07/13 05:04

#前提・実現したいこと
ReactでSPAを開発しています。
状態管理はRedux(redux toolkit)を使用しており、react-routerでroutingしています。
サーバーはCloud Firestoreを使用しています。
TwitterやInstagramなど、よくあるSNSと同じように、
投稿を一覧表示するページ(postsコンポーネント)で特定の投稿をクリックすると、当該投稿の詳細(postコンポーネント)へ遷移するような構成を実装しています。

https://hogehoge.app/posts -> https://hogehoge.app/posts/0001

一覧表示ページを経由する(postsコンポーネントをrenderする)ことなく、任意の投稿詳細URLへ直接アクセスしても当該投稿が適切に表示されるようにしたいです。

#発生している問題
現在は投稿の一覧をサーバーから取得する処理をpostsコンポーネントで行なっているため、
直接特定の投稿へアクセスするとState内に値が存在せず、適切に表示することができません。

typescript

1//投稿を一覧表示するpostsコンポーネント 2const Posts: React.FC = () => { 3 const dispatch = useDispatch(); 4 const posts = useSelector((state: RootState) => state.post.posts); 5 6 useEffect(() => { 7 dispatch(initPosts()); 8 }, []); 9// 以下、DOMを描画するJSXの処理 10 return ( 11 <>...</> 12 ) 13}

typescript

1//投稿の詳細を表示するpostコンポーネント 2const Post: React.FC<UnitProps> = props => { 3 const posts = useSelector((state: RootState) => state.post.posts); 4 5 const id: string = props.match.params.id; 6 const post: PostData | undefined = posts.find(p => p.id === id); 7 8 9 let postDetail = null; 10 if( typeof post === 'undefined') { 11 postDetail = (<p>Post with id {id} doesn't exist.</p>); 12 } else { 13 postDetail = .... //投稿詳細を表示するJSX 14 } 15 return ( 16 <>{postDetail}</> 17 );

上記のようなコードを書いているのですが、直接特定の投稿詳細URLにアクセスすると、当然postがundefinedになります。postsコンポーネント経由で遷移しても、再読み込みを行うとStateがリセットされ、同様の問題が発生します。

#試してみたこと
postコンポーネント内で、Stateから取得した投稿の配列(posts)がundefinedの場合はinitPostsをdispatchする、という処理を試してみましたが、下記のようなエラーが出たため、適切ではないと判断しました。

React Hook “useEffect” is called conditionally

現在は、postコンポーネント内での当該投稿の取得ロジックを変更し、下記のようなカスタムフックにすることを検討しています。
0. State内の投稿一覧(posts)を参照する
0. posts内に当該投稿があるかを探す
0. ない場合、サーバーから当該投稿のみを取得する

ただ、もっと効率的な実装方法やデファクトのやり方があるのではないかとも考えています。
素人質問で恐縮ですが、考え方や参考情報のキーワードなどでもご提示いただけますと幸いです。
よろしくお願いいたします。

#使用している環境
react-router@5.1.8
react-redux@7.1.9
reduxjs/toolkit@1.3.6
types/react@16.9.35

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

個人的にはposts一覧とpostは使いたいデータが違う場合が多いと思うので、そもそも別のデータ構造として定義してAPIのエンドポイントを変えてしまうのがベターかと思っています。
自分なら /posts/:id にアクセスしたタイミングでpostを分岐せずfetchするように作りそうです。

また、Reactのコンポーネント内で useEffectuseSelector を直接使うのではなくて、 usePost のようなcustom hookを定義してロジックをそちらに押し込むことで、コンポーネントの実装はシンプルに保てるかと思います。

投稿2020/07/13 05:49

yuki-yano

総合スコア132

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuki-yano

2020/07/13 05:54

すみません、FireStoreでしたね。 通常のバックエンドの実装前提で答えてしまっていました。 FireStoreをあまり使ったことがないので怪しいのですが、基本的には `/posts` と `/post` で同じデータ構造を返すのが一般的なのでしょうか。 `/posts` で不要なデータまで返していると通信量が肥大化してしまいそうなので、可能であればフロントが必要なプロパティのみ返すなどの方がベターには感じます。
tacro

2020/07/13 07:33

ご回答ありがとうございます。 FireStoreですと、データはdocumentという単位がcollectionという塊で保存されており、 document単体を呼び出すメソッドと、collection全体を呼び出すメソッドがあると理解しています。 (NoSQL構造のため融通が効きづらいのかもしれません) https://firebase.google.com/docs/firestore/query-data/get-data ただ、確かにおっしゃる通り、postsとpostでそれぞれ別のCustom hookを定義するのが良いように思いました。
yuki-yano

2020/07/13 07:42

なるほど、設計がかなり難しそうですね。 書いた後に思ったのですが、URLを遷移した際に古いデータが残ったままというのはあまりよくなさそうなので、データの有無に関係なくfetchして最新のデータを取ってきた方がよいかもしれないとは思いました。
tacro

2020/07/15 00:18

お返事ありがとうございます! >URLを遷移した際に古いデータが残ったままというのはあまりよくなさそうなので、データの有無に関係なくfetchして最新のデータを取ってきた方がよいかもしれない この考えは頭の中にありませんでした。 最新のデータをとってくるようにしようと思います!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問