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

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

新規登録して質問してみよう
ただいま回答率
85.46%
Next.js

Next.jsは、Reactを用いたサーバサイドレンダリングなどを行う軽量なフレームワークです。Zeit社が開発しており、nextコマンドでプロジェクトを作成することにより、開発環境整備が整った環境が即時に作成できます。

REST

REST(Representational State Transfer)はwebアプリケーションの構築スタイルの一種です。HTTP GET/POSTによってリクエストを送信し、レスポンスはXMLで返されます。SOAPのようなRPCの構築と比べるとサーバからクライアントを分離することが出来る為、人気です。

React.js

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

Q&A

解決済

1回答

1516閲覧

【Next.js, Context API】REST API で取得したデータをContext

matsuo_basho

総合スコア88

Next.js

Next.jsは、Reactを用いたサーバサイドレンダリングなどを行う軽量なフレームワークです。Zeit社が開発しており、nextコマンドでプロジェクトを作成することにより、開発環境整備が整った環境が即時に作成できます。

REST

REST(Representational State Transfer)はwebアプリケーションの構築スタイルの一種です。HTTP GET/POSTによってリクエストを送信し、レスポンスはXMLで返されます。SOAPのようなRPCの構築と比べるとサーバからクライアントを分離することが出来る為、人気です。

React.js

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

0グッド

0クリップ

投稿2021/11/21 10:14

編集2021/11/22 13:32

いつも大変お世話になっております。
現在Nextを利用してworpdressからRESTを利用して記事情報を取得しようとしています。

記事一覧にアクセスした際に10件分の記事情報を取得し、
記事情報は Context でグローバル管理をし、記事詳細ページで使い回しをしたいと考えています。

一応自分の方でそれっぽいソースを記述してみたのですが、
何度もサーバー側にリクエスト処理がかかってしまい(ループ処理のように)、
自分の考えているように動作してくれません。

今回の質問の着地地点としては、「REST APIで取得したデータをContext APIで管理をする」です。

どなたかわかる方がいらっしゃればご教授いただけますと幸いです。
それではどうぞ宜しくお願い致します。

ソースコード

bash

1# 使用しているファイルのみ記載 2. 3├── contexts 4│   └── PostsContext.jsx 5└── pages 6    ├── _app.js 7    ├── api 8    └── index.js

javascript

1 2# context/PostsContext.jsx 3 4import {createContext, useState} from "react"; 5 6const PostsContext = createContext({}); 7 8const PostsProvider = ({children}) => { 9 10 const [posts, setPosts] = useState({}) 11 12 const fetchPosts = async () => { 13 try { 14 15 const res = await fetch('xxxxxxx/wp-json/wp/v2/posts'); 16 const posts = await res.json(); 17 18 setPosts(posts); 19 20 } catch (err) { 21 console.error(err); 22 } 23 }; 24 25 return ( 26 <PostsContext.Provider value={{posts, fetchPosts}}> 27 {children} 28 </PostsContext.Provider> 29 ) 30 31} 32 33export {PostsContext, PostsProvider}; 34

javascript

1 2# pages/_app.js 3 4import '../styles/globals.css' 5import {PostsProvider} from "../contexts/PostsContext"; 6 7function MyApp({Component, pageProps}) { 8 return ( 9 <PostsProvider> 10 <Component {...pageProps} /> 11 </PostsProvider> 12 ) 13} 14 15export default MyApp

javascript

1 2# pages/index.js 3 4import Head from 'next/head' 5import {useContext} from "react"; 6import {PostsContext} from "../contexts/PostsContext"; 7 8export default function Home() { 9 10 const {posts, fetchPosts} = useContext(PostsContext); 11 12 fetchPosts(); 13 14 console.log(posts); 15 16 return ( 17 <></> 18 ) 19} 20

# 修正後ソース

javascript

1 2# context/PostsContext.jsx 3 4import {createContext, useState} from "react"; 5import {useEffect} from "react"; 6 7 8const PostsContext = createContext({}); 9 10const PostsProvider = ({children}) => { 11 12 const [posts, setPosts] = useState({}) 13 14 useEffect(async () => { 15 16 const res = await fetch('xxxxxxx/wp-json/wp/v2/posts'); 17 const posts = await res.json(); 18 19 setPosts(posts); 20 21 }, [setPosts]) 22 23 return ( 24 <PostsContext.Provider value={{posts}}> 25 {children} 26 </PostsContext.Provider> 27 ) 28 29} 30 31export {PostsContext, PostsProvider}; 32

javascript

1 2# pages/index.js 3 4import Head from 'next/head' 5import {useContext} from "react"; 6import {PostsContext} from "../contexts/PostsContext"; 7 8export default function Home() { 9 10 const {posts} = useContext(PostsContext); 11 12 console.log(posts); 13 14 return ( 15 <></> 16 ) 17}

出力

イメージ説明

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

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

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

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

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

guest

回答1

0

ベストアンサー

「REST APIで取得したデータをContext APIで管理をする」

この点についてはAPIのレスポンスがわからないのでなんとも言えませんが、

何度もサーバー側にリクエスト処理がかかってしまい(ループ処理のように)、

については関数コンポーネントのトップレベルでfetchPosts();を実行しているのが問題だと思われます。useEffectsなどを使用して、特定のタイミングでのみ実行されるようにしてください。

投稿2021/11/22 10:52

k4a

総合スコア983

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

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

matsuo_basho

2021/11/22 13:29

ありがとうございます! ひとまず、fetchPosts()を削除し、useEffect()を利用した書き方に変更をしました。 無事にループ処理的な動作からは解放されましたが、 console.logを1度すると、コンソール上に以下の2行が出力されています。 {} (10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}] これはなぜ2回もconsole.log()が処理されているのでしょうか、、? 修正後のソースコードを追記しております。
k4a

2021/11/22 13:49

それも同じ理由です。 `console.log()`が関数コンポーネントのトップレベルに有ることが原因です。 初回レンダリング時に`post`が`{}`(初期値)の状態で一度実行され、post(state)が更新されたので再レンダリングされて再度実行され`post`に設定された値が出力されています。 useEffectsの依存配列にセット関数のsetPostsを渡すのは違う気がします。セット関数は変化しないので依存配列に入れる意味がわかりません。初回レンダリングのみ実行するという意思なら空配列を指定すべきです。
matsuo_basho

2021/11/23 04:21

ありがとうございます! 初回レンダリング時に console.log(posts); が一度実行され、 再レンダリング時にもう一度実行されたということですね。 useEffects() についてもありがとうございます! 修正致しました! 最後の質問をさせてください。 自分は最終的に外部から取得したデータをContext API(この例だとposts)に格納し それをいろんなページで使い回しをしたいと考えているのですが、 getStaticProps() や getServerSideProps() 内では useContext() を利用することができないようで、現在のように Home() 内で useContext() を利用する形になっています。 実際この方法だと、Context API(posts)にデータを格納することができていますが、 例えば今回のようにコンソール上に初期値の{}が出力されたり、 ページのコンテンツが遅いなど、あまり望ましくない結果となってしまいます。 そもそも自分が行いたい「外部から取得したデータをContext API(この例だとposts)に格納」というのはこの方法で合っているのでしょうか??
k4a

2021/11/23 04:41

> 例えば今回のようにコンソール上に初期値の{}が出力されたり、 それは実装の問題でContext API等に関わる問題ではありません。 > ページのコンテンツが遅いなど `getServerSideProps`から渡したpropsをコンポーネント内でContextに注入すればよいのではないですか?データの取得がバックエンドかフロントエンド化の違いでコンテンツのレンダリング速度に有意な差が出るとは思えませんが。 `getStaticProps`はSSGなので外部から取得するにはあまり適していないように思います。
matsuo_basho

2021/11/24 06:18

いつも素早くご回答いただきありがとうございます! なるほど、、せっかくk4aさんがご丁寧に説明いただいているにもかかわらず なかなか理解ができないので、基礎知識の部分がかなり不足してる気がします、、。 一旦書籍等を購入して体系的に学び直したいと思います! ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問