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

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

ただいまの
回答率

90.50%

  • React.js

    832questions

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

  • Redux

    112questions

React Redux Cannot read property 'map' of undefinedのエラー

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 592

Y-A-A

score 3

React,Reduxでリスト中の項目をクリックすると詳細が表示される、という仕組みを作りたいです。
リストを表示するRecipesというコンポーネントを作ったのですが、コンポーネント内で「TypeError: Cannot read property 'map' of undefined」のエラーが出てしまいます。
RecipeListが上手く読み込めていないのかと思いますが、reducersからcomponentsのどこで受け渡しに失敗しているのかわかりません。

どのように修正したら良いのかアドバイスをお願いいたします。
可能であれば、このような時にどの段階で(reducer、container、componentsのどこで)要素の受け渡しに失敗しているのか、確認する方法も合わせて教えていただけますと幸いです。

よろしくおねがいします。

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from 'react-redux';
import {createStore} from 'redux';
import registerServiceWorker from './registerServiceWorker';

import App from './components/App';
import rootReducer from './reducers';

const store = createStore(rootReducer);


ReactDOM.render(
    <Provider store={store}>
    <App />
    </Provider>,
 document.getElementById('root')
);

reducers/RecipesReducers.js

const RecipesReducer = () => {
    return [
        {title: '白米', image: '', author: '白米さん', comment: '白くてピカピカ'},

        {title: '卵焼き', image: '', author: '卵さん', comment: 'しっとりふわふわ'},

        {title: '味噌汁', image: '', author: '味噌汁さん', comment: '温かくて身体にしみる!'}
    ]
}

export default RecipesReducer;

containers/RecipeList.js

import {connect} from 'react-redux';
import Recipes from '../components/Recipes';


const mapStateToProps = state => {
  return{
    recipeList: state.recipesReducer
  };

}


export default connect (mapStateToProps, null)(Recipes);


components/Recipes.js

import React from 'react';

const Recipes = ({RecipeList}) => {
//↓この行でエラーが出ます
 const list = RecipeList.map(recipe => {
        return(
          <li key = {recipe.title} > 
          {recipe.title}
          </li>
        );
      });
 return <ul>{list}</ul>
      }

export default Recipes;


components/App.js

import React from 'react';
import {Component} from 'react';

import Recipes from '../containers/RecipeList'
import RecipeDetail from '../containers/RecipeDetail'


const App = () => {
    return (
      <div>
        <Recipes />
        <RecipeDetail />
      </div>
    );
  };

  export default App;
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

const mapStateToProps = state => {
  return{
    recipeList: state.recipesReducer
  };
}

としているので、

const Recipes = ({RecipeList}) => {
//↓この行でエラーが出ます
 const list = RecipeList.map(recipe => {

は、

const Recipes = ({ recipeList }) => {
//↓この行でエラーが出ます
 const list = recipeList.map(recipe => {

の間違いではないでしょうか。

もしかすると他の部分に原因があるかもしれませんが、
その場合は掲載されていない他のファイルのコードも全て載せてみてください。

import rootReducer from './reducers';

特に、この読み込んでいるファイルなどですね。

可能であれば、このような時にどの段階で(reducer、container、componentsのどこで)要素の受け渡しに失敗しているのか、確認する方法も合わせて教えていただけますと幸いです。

今回のエラーはTypeError: Cannot read property 'map' of undefinedなので、Recipesコンポーネントのpropsに渡ってくることを期待しているRecipeListundefinedであることが分かります。

なので、Recipesコンポーネントの前のどこかに原因があると言えます。

const mapStateToProps = state => {
  //確認
  console.log(state);

  return{
    recipeList: state.recipesReducer
  };
}

その上で今度はひとつ手前のところで、mapStateToPropsの引数に渡ってくるstateに期待通りの値が存在しているかをチェックしてみましょう。

ここで問題がなければ、これ以降が原因ですし、ここに問題があれば、その手前のreducer周りに問題があると言えます。(さらにそれより以前のところに問題がある可能性もあります)

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/14 22:53

    ご回答ありがとうございます。
    さっそく
    const Recipes = ({ recipeList }) => {
    の点を修正しましたが、同様のエラーが出ております。

    追加のコードも載せますのでご確認いただけますでしょうか。

    reducers/index.js

    import {combineReducers} from 'redux';
    import RecipesReducer from './RecipesReducer';
    //import ActiveRecipe from './ActiveRecipe';


    const rootReducer = combineReducers({
    RecipesReducer : RecipesReducer,
    // selectedRecipe: ActiveRecipe
    });

    export default rootReducer;

    レシピをリストから選択した際はonClickでイベントを呼ぶ予定ですが、現在はリストの表示のみを確認したいので一部コメントアウトしています。
    呼び出す予定のイベントに関するコードも念のために下記に貼り付けます。

    reducers/ActiveRecipe.js

    //const ActiveRecipe = (state= null, action) =>{
    // switch(action.type){
    // case 'RECIPE_SELECTED':
    // return action.payload;
    // };

    // return state;
    //}
    //export default ActiveRecipe;


    containers/RecipeDetail.js

    //import React, {Component} from 'react';
    //import {connect} from 'react-redux';
    //import RecipeDetail from '../components/RecipeDetail';

    //const mapStateToProps = state => {
    // return {
    // selectedRecipe: state.activeRecipe
    // }
    //}

    //export default connect(mapStateToProps, null)(RecipeDetail)


    components/RecipeDetail.js

    //import React from 'react';

    //const RecipeDetail = ({SelectedRecipe=[]})=> {
    // return(
    // <div>
    // <p>タイトル:{this.recipe.title}</p>
    // <p>コメント:{this.recipe.comment}</p>
    // <p>作者:{this.recipe.author}</p>
    // </div>
    // )
    // }

    //export default RecipeDetail;


    actions/index.js

    export function selectRecipe(recipe){
    return{
    type: 'RECIPE_SELECTED',
    payload: recipe
    };
    }


    よろしくお願いいたします。

    キャンセル

  • 2018/05/14 22:55 編集

    コメント欄ですとコードブロックが効かず読みづらいので、質問文に追記として追加情報を載せて頂けますか?また、ログ出力の結果も追記して下さい。(※回答の追記を要参照)

    キャンセル

  • 2018/05/14 22:59 編集

    const rootReducer = combineReducers({
    recipesReducer : RecipesReducer,
    });

    このように修正して再度、試して見て下さい。

    キャンセル

  • 2018/05/14 23:03

    ↑これでエラーが治らない場合は、以下を質問文に反映させて下さい。(少し外に出てしまうので、その間に対応してみて下さいということで)

    (1)回答に追記したデバッグ参考情報をもとに、各ステップにログを差し込み関連する値を確認。その結果を質問文に追記。
    (2)現象を再現するために必要なコードを全て質問文に追記。ただし、現象を再現するにあたり不要なコードはノイズになるので、それらは除外。あくまで現象を再現するための最小限のコードを追記。

    キャンセル

  • 2018/05/14 23:09

    回答が遅くなりすみません。

    const rootReducer = combineReducers({
    recipesReducer : RecipesReducer,
    });

    こちらに書き換えたらリストが表示されました!
    ありがとうございます。

    これは右側のRecipesReducerがreducers/RecipesReducer.jsで書いた配列で、左側がcontainers/RecipeList.jsにあるrecipesReducerだという理解で良いでしょうか?
    名前が違うので渡せていなかったんですね…。

    本当にありがとうございます。
    console.log(state)での確認、これから使わせていただきます。

    キャンセル

  • 2018/05/15 00:21

    > 右側のRecipesReducerがreducers/RecipesReducer.jsで書いた配列で
    配列ではありません。RecipesReducers.jsでexportしているものを確認していただくと分かると思いますが、exportしているのは関数です。なので、右側は関数です。

    > 左側がcontainers/RecipeList.jsにあるrecipesReducer

    「state.recipesReducer」のことですよね?厳密に言うと違いますが、結果的にはそうなります。
    combineReducers関数はstate objectを作りますが、そのobjectのkeyとなるのが今回の例でいうと、左側の「recipesReducer」です。なので、state.recipesReducerで参照可能になるという訳です。

    ※質問が解決した場合はベストアンサーをつけて質問を閉じて下さい。

    キャンセル

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

  • ただいまの回答率 90.50%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • React.js

    832questions

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

  • Redux

    112questions