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

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

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

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

React.js

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

Q&A

解決済

2回答

1329閲覧

axiosで取得した結果をReactでsetStateしたいが、初回のみうまくセットされない。

sasa0330

総合スコア64

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

React.js

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

0グッド

1クリップ

投稿2022/09/10 07:26

編集2022/09/10 08:19

前提

Reactでaxiosを使ってAPIの情報を取得
responsの中の必要な情報を連想配列にしてstateに追加したい。
が、1回目の取得時のみ追加されない。

実現したいこと

飲食店の情報を取得できるAPIを使い、
必要な店舗の情報のみを抜き出して連想配列にまとめたい。

JavaScript(React)

以下のようにsetShoplistで店舗に紐づく情報を1店舗ずつ取得したいのですが、
finallyでconsole.log(shopList);すると[]となり、情報が取得できていませんでした。
取得ができないのは画面更新して1回目の時のみで、2回目は取得できます。

取得件数が0件でないことは確認済みです。

const [shopList, setShoplist] = useState([]); const getShopList = () => { axios.get(requestUrl) .then(function (response) { // handle success const responseShopList = response.data.results.shop; for (const item of responseShopList) { //ここでうまく情報をセットできていない感じがする setShoplist((prevState) => [...prevState, { id: item.id, photoPcM: item.photo.pc.m, shopName: item.name, lunch: item.lunch, budgetName: item.budget.name, large_areaName: item.large_area.name, Access: item.access } ]); } }) .catch(function (error) { // handle error }) .finally(function () { // always console.log(shopList); }); }

最終的にshopListの値が以下のようになるのが理想です。

json

1[ 2 //1店舗目の情報 3 { 4 id:"XXXX", 5 photoPcM:"XXXX", 6 shopName:"XXXX", 7 lunch:"XXXX", 8 budgetName:"XXXX", 9 large_areaName:"XXXX", 10 Access:"XXXX" 11 }, 12 //2店舗目の情報 13 { 14 id:"XXXX", 15 photoPcM:"XXXX", 16 shopName:"XXXX", 17 lunch:"XXXX", 18 budgetName:"XXXX", 19 large_areaName:"XXXX", 20 Access:"XXXX" 21 }... 22]

console.log(shopList);すると[]となり、情報が取得できていませんでした。

この原因がわかる方、よろしくお願いします。

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

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

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

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

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

guest

回答2

0

ベストアンサー

then のコールバックの中でsetShoplist したことによってstateの変更が即座に反映されて変更後のshopListfinally のコールバックの中ですぐに確認できるわけではないです。

ですので、console.logしている行を、質問にあるコードが記載されたコンポーネントの中で JSXをreturnする直前に移動してみるといかがでしょうか?

サンプル的なコードで説明すると以下のような感じの移動です。

diff

1 .finally(function () { 2 // always 3- console.log(shopList); 4 }); 5 } 6 7 useEffect(getShopList, []); 8 9+ console.log(shopList); 10+ 11 return ( 12 <div className="shop-list">

補足

質問にあるコードだとレスポンスに含まれる配列 response.data.results.shopの含む要素の個数分、forループが回ってその回数だけ setShoplist でstate更新をしてしまうことになりますが、それを避けるため以下のようにするとよいかと思います。

diff

1- const responseShopList = response.data.results.shop; 2- for (const item of responseShopList) { 3- //ここでうまく情報をセットできていない感じがする 4- setShoplist((prevState) => [...prevState, 5- { 6- id: item.id, 7- photoPcM: item.photo.pc.m, 8- shopName: item.name, 9- lunch: item.lunch, 10- budgetName: item.budget.name, 11- large_areaName: item.large_area.name, 12- Access: item.access 13- } 14- ]); 15- } 16+ const responseShopList = response.data.results.shop.map(item => ( 17+ { 18+ id: item.id, 19+ photoPcM: item.photo.pc.m, 20+ shopName: item.name, 21+ lunch: item.lunch, 22+ budgetName: item.budget.name, 23+ large_areaName: item.large_area.name, 24+ Access: item.access 25+ } 26+ )); 27+ setShoplist((prevState) => [...prevState, ...responseShopList]);

投稿2022/09/10 09:24

編集2022/09/10 09:45
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

maisumakun

2022/09/10 09:29

別件での再描画が入って必要以上に出すぎることが考えられるので、useEffect([shopList])で囲んでおいたほうがいいかなと思います。
sasa0330

2022/09/19 07:56

ありがとうございます! ループの時に何度もstateを更新するとそれ分描画されるということですね。勉強になります。 +αの回答もありがとうございます。
guest

0

finallyでconsole.log(shopList);すると[]となり、情報が取得できていませんでした。

できなくて正常です。

外側でshopListconstで宣言してあるように、一連の実行中はshopListは変化せず、コンポーネントが再描画されて初めてshopListは新しい値となります。

投稿2022/09/10 09:16

maisumakun

総合スコア145183

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

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

maisumakun

2022/09/10 09:24

> 取得ができないのは画面更新して1回目の時のみで、2回目は取得できます。 2回目以降も、表示されているのは「更新前の値」のはずです。
sasa0330

2022/09/19 07:54

ありがとうございます! なんとなくですが理解できました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問