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

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

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

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

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

React.js

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

Q&A

解決済

2回答

873閲覧

React,Redux-SagaでAPIを叩く毎に、 storeのstateの配列に、配列を追加させ、 画面に表示させたいです。

takada.m

総合スコア0

Redux

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

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

React.js

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

0グッド

0クリップ

投稿2020/06/03 07:27

編集2020/06/04 03:46

前提・実現したいこと

React,Redux-SagaでAPIを叩く毎に、
storeのstateの配列に、配列を追加させ、
画面に表示させたいです。

  1. 初期レンダー

問題なく表示される

0. 再レンダーのためのAPIを叩く
レスポンスはきちんと返ってきてる

0. リデューサーでエラー

0. 再レンダーされない

 

※APIからのレスポンスは初期レンダー時も、再レンダー時もJSONの配列が返ってくる。

※以下の処理以外は問題なく動作をしている。




 

◆現在のコード
action.js

export const REQUEST_FETCH = 'REQUEST_FETCH'; export const SUCCESS_FETCH = 'SUCCESS_FETCH'; export const FAILED_FETCH = 'FAILED_FETCH'; export const REQUEST_REFETCH = 'REQUEST_REFETCH'; export const SUCCESS_REFETCH = 'SUCCESS_REFETCH'; export const FAILED_REFETCH = 'FAILED_REFETCH'; // API export const requestFetch = () => ({ type: REQUEST_FETCH, }); // API成功 export const succeedFetch = (response) => ({ type: SUCCESS_FETCH, respose, }); // APIエラー export const failedFetch = (error) => ({ type: FAILED_FETCH, error, }); // 再レンダーAPI export const requestReFetch = (results) => ({ type: REQUEST_REFETCH, }); // 再レンダーAPI成功 export const succeedReFetch = (results) => ({ type: SUCCESS_REFETCH, results, }); // 再レンダーエラー export const failedReFetch = (results) => ({ type: FAILED_REFETCH, results, });

 
reducer.js

import { REQUEST_FETCH, SUCCESS_FETCH, FAILED_FETCH, REQUEST_REFETCH, SUCCESS_REFETCH, FAILED_REFETCH, } from './action'; const initialState = { isFetching: true, isError: false, response: {}, }; const Reducer = (state = initialState, action) => { switch (action.type) { // API case REQUEST_FETCH: return { ...state, }; // API成功 case SUCCESS_FETCH: return { ...state, isFetching: false, isError: false,      response: action.response, }; // APIエラー case FAILED_FETCH: return { ...state, isFetching: false, isError: true, response: action.error, }; // 再レンダーAPI case REQUEST_REFETCH: return { ...state, }; // 再レンダーAPI成功 case SUCCESS_REFETCH: return { ...state, isFetching: false, // *** 問題のコード *** response: [...state.response, action.results],      // 以下も試しましたが、同じくエラー // response: state.response.concat(action.results), }; // 再レンダーAPIエラー case FAILED_REFETCH: return { ...state, isFetching: false, isError: true, response: action.reError, }; default: return state; } };

一応saga.jsも記載します。

import Api from './api'; import { call, put, takeEvery } from 'redux-saga/effects'; import { REQUEST_FETCH, succeedFetch, failedFetch, REQUEST_REFETCH, succeedReFetch, failedReFetch, } from './action'; // API操作 function* fetchData() { const { response, error } = yield call(Api); if (response) { yield put(succeedFetch(response)); } else { yield put(failedFetch(error)); } } // 再レンダー function* reFetchData() { const { results, reError } = yield call(Api); if (results) { yield put(succeedReFetch(results)); } else { yield put(failedReFetch(reError)); } } const mySaga = [ takeEvery(REQUEST_FETCH, fetchData), takeEvery(REQUEST_REFETCH, reFetchData), ]; export default mySaga;

 

理屈的にも、
記載方法としても間違っていないように見えるのですが、
以下のエラーが出てしまいます。

発生している問題・エラーメッセージ

スプレッドで記載の場合

TypeError: state.response is not iterable

concatで記載の場合

TypeError: state.response.concat is not a function

該当のソースコード

reducer.js

response: [...state.response, action.results],
response: state.response.concat(action.results),

  




色々書き方を変えて試してみましたが、
エラーがなくならないか、違う結果になってしまいます。

試したこと

  • actionでの受け取り方を変える
export const succeedReFetch = (results) => ({ type: SUCCESS_REFETCH, response: results, });
export const succeedReFetch = (results) => ({ type: SUCCESS_REFETCH, response: [results], });

 

  • reducerでの受け取り方を変える
case SUCCESS_REFETCH: return { ...state, response: {...state.response, action.results}, // response: state.response.concat([action.results]), };
case SUCCESS_REFETCH: return Object.assign({}, state, { response: [...state.response, action.results], });

以下は再レンダーされるが、追加ではなく、中身が丸々入れ替わってしまう。

case SUCCESS_REFETCH: return { response: action.results, });

 


いずれもエラーや望む結果を得る事はできませんでした。
上記ばかりを書き換えてみましたが、別の視点が考えられるでしょうか。
解決策をご教示いただけますと幸いです。

※タイポあったら申し訳ございません。

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

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

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

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

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

hoshi-takanori

2020/06/03 08:36

action.js における reFetch の引数 results には何を渡してますか? また、saga.js を見ると REFETCH は再フェッチの開始だと思いますが、reducer.js を見ると REFETCH の時点で結果を更新しているような…。
takada.m

2020/06/03 09:08

resultsにはApiを叩いたresponse.dataの配列を渡しています。 requestFetchも同様のApiを叩いて、同じくresponse.dataの配列を渡しています。 この問題が解決しないため、 saga.jsでは分けていますが、パラメータが違うだけで、 同じようなJSONの配列が返ってきています。 で、発火のタイミングをずれている、という感じです。 REQUEST_FETCHは初期表示時に発火、 REFETCHはonClick時に発火します。 ご質問の内容にそっているでしょうか?
hoshi-takanori

2020/06/03 09:19

saga.js では REQUEST_FETCH と REFETCH がフェッチ開始で、フェッチ成功したらどちらの場合も succeedFetch が呼ばれると思うのですが、reducer.js では REFETCH つまり再フェッチ開始の時点で結果を格納してるように見えるのですが…。
takada.m

2020/06/04 00:33

失礼いたしました。 タイポがあったため、修正いたしました。 正しくは以下になります。 // 再レンダー function* reFetchData() { const { results, error } = yield call(Api); if (results) { // yield put(succeedFetch(results)); タイポのため以下に修正 yield put(succeedReFetch(results)); } else { // yield put(failedFetch(error)); タイポのため以下に修正 yield put(failedReFetch(error)); } }
hoshi-takanori

2020/06/04 01:18

それはもうタイポというレベルじゃないですよね。 最初のフェッチは REQUEST_FETCH, SUCCESS_FETCH, FAILED_FETCH なので、 再フェッチも REQUEST_REFETCH, SUCCESS_REFETCH, FAILED_REFETCH になってる (すべき) ってことなのでは。
takada.m

2020/06/04 03:46

ご指摘ありがとうございます。 コード修正いたしました。 ただ結果は同じでエラーが発生します。
guest

回答2

0

こんにちは

initialStateresponse を以下のように、空配列に修正するといかがでしょうか?

diff

1const initialState = { 2 isFetching: true, 3 isError: false, 4- response: {}, 5+ response: [], 6};

追記

PR#1 の作業ブランチ、

の現状で動画確認した画面キャプチャが以下です。

イメージ説明

redux-logger によって、REQUEST_FETCHアクションとSUCCEED_FETCHアクションがdispatchされているのを、Consoleから確認できています。

投稿2020/06/03 08:06

編集2020/06/04 07:06
jun68ykt

総合スコア9058

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

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

takada.m

2020/06/03 08:11

``` TypeError: state.response is not iterable ``` 同様のエラーでした。
jun68ykt

2020/06/03 08:24 編集

なるほどですね。それでは、問題の以下の箇所 case REFETCH: return { ...state, // *** 問題のコード *** response: [...state.response, action.results], で、 [...state.response, action.results] と、スプレッド構文を使っているところで、 state.response が配列になっていないように思えますので case REFETCH: の直後に console.log(state.response); とデバッグログを入れて case REFETCH: console.log(state.response); // これを追加 return { ...state, // *** 問題のコード *** response: [...state.response, action.results], とすると、追加したログで、配列が Consoleに出力されますでしょうか?
takada.m

2020/06/03 08:58

試してみましたが、配列が出力されます。 REQUEST_FETCHでも同じくconsole.logで出力してみましたが、 配列が出力されます・・・。
jun68ykt

2020/06/04 01:40

state.response が配列であるのに、 response: [...state.response, action.results], の行で TypeError: state.response is not iterable というエラーには、ならないと思います。 要望なのですが、お手元のソースコードのすべて(package.jsonやindex.jsも含めて)を Github に上げていただくことは可能でしょうか?
takada.m

2020/06/04 06:04 編集

https://github.com/masatoshiTakada/react-redux-sample こちらに上げさせていただきました。 コードは少し簡略化しているので、私の持っているもの全く同じではないのですが、 エラーは同じものが出ております。 ご確認いただけますと幸いです。
takada.m

2020/06/04 06:02

追記: mockAPI.yamlをStoplight Studioで起動してAPIを叩いています。
jun68ykt

2020/06/04 06:16

ありがとうございます。 とり急ぎ fork して 手元に clone しました。原因が分かったらまたコメントします。
takada.m

2020/06/04 06:18

お手数おかけしますが、よろしくお願いいたします。
jun68ykt

2020/06/04 07:01

見ました。 結論からいうと間違ってなさそうです。 以下、当方の手元で行ったことです。 手元にclone して yarn install 、yarn start したところ、アプリの起動には成功しましたが、mock API http://localhost:3100/testlist を立ち上げるまでの設定に手間取りそうだったので、mockable.io で代替したところ、意図通り、AXIOS経由で配列がとれて、要素分の table が render されました。 mockableに作ったAPIは以下です。 https://demo2746340.mockable.io/q267220/testlist このご質問の本題とは関係ありませんが、他にもいくつか手を入れたのでPRしました。 https://github.com/masatoshiTakada/react-redux-sample/pull/1 不明点あればコメント頂ければと思います。
takada.m

2020/06/04 07:49

ありがとうございます。 こちらも確認させていただきました。 間違ってないように思うのですが、 配列に追加ができないんですよね。 何か他に思い付くことはありますでしょうか。
jun68ykt

2020/06/04 08:22

すみません。先ほどのコメントで > 結論からいうと間違ってなさそうです。 と書いたのは、 REQUEST_FETCH が成功してデータ数分のtableが表示されるところまででした。 「更新」をクリックするとエラーが再現されました。 ちょっと見てみます。
jun68ykt

2020/06/04 08:55

問題を解決しました。 ご提示の元のコードの何がちょっと拙いかというと、欲しいのは配列であるのに、リデューサー のinitialStateの中で response: {}, としており、レスポンス全体を受け取ろうとしていることかと思います。なので、 この response: {}, を、 arrayExample: [], とすれば、分かりやすくなると思います。このような趣旨で修正を追加しましたので、以下のPRをご覧いただければと思います。 https://github.com/masatoshiTakada/react-redux-sample/pull/1 上記のPRですが,問題なさそうであれば、master にマージいただいてもよいですし、修正の方針が把握できたらクローズいただいてもかまいません。 参考になれば幸いです。
jun68ykt

2020/06/04 08:57

追伸 修正コミットの中で、mainState の中の response を arrayExample に変更したコミットは以下です。 https://git.io/JfXcS
jun68ykt

2020/06/04 09:02

追伸2 respose を arrayExample に置き換えたのにともなって、error というプロパティも追加しています。この error があれば isError は不要になるかもしれません。
takada.m

2020/06/04 09:21

ありがとうございます! 確認できました! 望んでいた動きです! 本当に本当に助かりました! まだここの使い方がよくわからないので、 明日ベストアンサーします!
jun68ykt

2020/06/04 16:11

どういたしまして???? > 望んでいた動きです! とのことでよかったです ???? > まだここの使い方がよくわからないので、 > 明日ベストアンサーします! はい。今後もteratail を利用するのでしたら、投稿した問題についてすべての疑問が解消したら、問題を 解決済み にすることをお勧めします。 それと、私の「Githubにソースを入れてくれませんか?」という要望に速やかに応えて頂いたのは、とてもよかったです。回答者がcloneして、yarn install , yarn start すれば、すぐに問題を再現できるようにしておくのは、ちょっと手間かもしれませんが、その分、的を射た回答が集まりやすくなるでしょう。
takada.m

2020/06/15 23:55

jun68ykt様 回答が遅くなってしまい大変申し訳ございません。 諸事情にで業務を行えずにおりました。 コードのことだけでなく、色々なアドバイスまでいただき本当にありがとうございます。 感謝いたします。 これにてクローズいたします。
guest

0

自己解決

reducer.jsの配列を追加したい部分を以下のようにすることで解決できました!

JavaScript

1response: { 2 patientInfoList: [ 3 ...state.response, 4 ...action.results, 5 ], 6},

解決にご協力いただいたエンジニアの方に感謝です!
ありがとうございました!

投稿2020/06/16 00:00

takada.m

総合スコア0

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問