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

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

ただいまの
回答率

90.33%

  • React.js

    919questions

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

  • Redux

    129questions

redux-form actionの初期値を表示する

解決済

回答 1

投稿 編集

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

Y-A-A

score 3

React, Redux, Redux-formを使って、入力フォームに記入した内容が送信ボタンが押された際にリストに追加されるという仕組みを作りたいです。
Redux-form公式のSimple Form Exampleを元に、入力フォームの内容をアラートで表示するところまでは出来ました。

しかし、入力した内容をリストに反映させようとするとうまくいきません。

Form.js→新規レシピの入力フォーム
RecipeList→レシピのリスト

です。

index.js/actions

export function handleChange(text){
    return{
        type: 'TEXT_CHANGED',
        text: text
    }
}

export function addRecipe(newrecipe){
    return{
        type: 'RECIPE_ADDED',
        payload: newrecipe
    }
}

AddRecipes.js/reducers

const AddRecipes = (state = initialState, action ) => {
    switch(action.type) {
         case 'RECIPE_ADDED': 
               return {...state, recipes: action.payload}};
         return state

    }


const initialState = {
    recipes:[
        {title: '白米', image: '5c0cdd2fa192df5c7a968734d0c49d7a_s.png', author: 'Aさん', ing:'お米', amount:'1合', howto:'お米を水で研ぐ。'}

};

export default AddRecipes;

index.js/actions

import {combineReducers} from 'redux';
import AddRecipes from './AddRecipes';
import {reducer as formReducer} from 'redux-form';



const rootReducer = combineReducers({
    form: formReducer,
    recipes :AddRecipes
    });

export default rootReducer;

Form.js/containers

import React, {Component} from 'react';
import {Field, reduxForm} from 'redux-form';
import { bindActionCreators } from 'redux';
import {handleSubmit} from '../actions/index';
import {addRecipe} from '../actions/index';


const Form = props => {
    const {handleSubmit, pristine, submitting} = props;

    return(
        <form onSubmit = {handleSubmit}>
        <div>
            <h3>新規レシピ</h3>
            <p>タイトル</p>
            <Field
                name = 'newtitle'
                label = 'newtitle'
                component="input"
            />
            <p>写真URL</p>
            <Field
                name = 'newimg'
                label = 'newimg'
                component="input"
            />
            <p>材料</p>
            <Field
                name = 'newing'
                label = 'newing'
                component="input"
            />
            <p>分量</p>
            <Field
                name = 'newamount'
                label = 'newamount'
                component="input"
            />
           <p>作り方</p>       
            <Field
                name = 'newstep'
                label = 'newstep'
                component="input"
            />
            <p>コツ・コメント</p>
            <Field
                name = 'newcomment'
                label = 'newcomment'
                component="input"
          />
        </div>
        <div>
            <button type = "submit" disabled = {pristine || submitting}> 
            送信
            </button>
        </div> 
        </form>
    )
}

export default reduxForm({
    form: 'addedrecipe', 
    fields: ['newtitle', 'newimg', 'newing','newamount','newstep', 'newcomment']
  })(Form);

RecipeList.js/containers

import React, {Component} from 'react';
import {connect} from 'react-redux';
import {addRecipe} from '../actions/index';
import {handleSubmit} from '../actions/index';
import {bindActionCreators} from 'redux';

class RecipeList extends Component{
  renderList(){
   let handleSubmit = (values) => {
      var data = {
          newtitle:values.newtitle,
          newimg: values.newimg,
          newing: values.newing,
          newamount: values.newamount,
          newstep: values.newstep,
          newcomment: values.newcomment
      }
      this.props.addRecipe(data)
  }
    return this.props.recipes.map((recipe)=>{
      return(
        <div onClick = {()=> this.props.activeRecipe(recipe)}>
        <p>{recipe.title}</p>    
        </div>
      );
    });
  }

  render(){
    return <ul>{this.renderList()}</ul>
    }
}

function mapStateToProps(state){
  return {
    recipes: state.recipes
  }
}

export default connect (mapStateToProps, mapDispatchToProps)(RecipeList);


App.js/components

import React, {Component} from 'react';
import RecipeList from '../containers/RecipeList'
import Form from '../containers/Form'
import { addRecipe } from '../actions';

export default class App extends Component{
  render(){
    return (
      <div>
        <Form onSubmit={addRecipe}/>
        <RecipeList />
      </div>
    );
  };
}

エラーの内容

AddRecipes.jsでinitialStateを定義しているので最初に読み込んだ時点でリストが出るはずですが、RecipeList.jsで'TypeError: this.props.recipes.map is not a function'のエラーがでます。

試したこと

console.logでinitialStateの内容が渡されているか確認したところ、index.js/reducersのrootReducerまでは渡されているようです。
reducer→container間の受け渡しに失敗しているのでしょうか?

まずはinitialStateを渡してRecipeListに反映させたいです。

参考サイト
redux-formは参考にできる日本語サイトが少なく困っています。

https://tnakamura.hatenablog.com/entry/2016/11/10/redux-form-field-array

↑最初はこちらのサイトを参考にしたのですが、一つのファイルにまとめて書かれているためファイルやフォルダ間の受け渡し方の参考には

https://stackoverflow.com/questions/44487844/how-to-add-data-to-store-through-redux-forms-in-react

↑こちらを読みました。しかし英語なので読み違えている部分があるかもしれません。

参考にできるサイトも併せて教えていただけると嬉しいです。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • 退会済みユーザー

    2018/05/23 00:28

    複数のユーザーから「やってほしいことだけを記載した丸投げの質問」という意見がありました
    「質問を編集する」ボタンから編集を行い、調査したこと・試したことを記入していただくと、回答が得られやすくなります。

  • HayatoKamono

    2018/05/23 01:11 編集

    「まずはinitialStateを渡してRecipeListに反映させていです。(原文のまま引用)」ということなので、今回の質問の範囲をまずは初期表示をさせるところまでに変更してください。(要タイトル修正、本文修正) 掲載されているコード量が多いのと、間違っていそうな箇所が散見されるので質問の範囲が広いと回答する側の負担が大きいです。 また、掲載するコードも前の質問のコメント欄でお伝えした通り、今回の質問に不要なコードはコードを読む側にとってノイズとなるので削り、現象を再現できる最小限のコードを用意して掲載してください。(3分の1〜5分の1くらいには削れそうな気がします)※現象を再現する最小限のコードを用意している過程で、原因が特定しやすくなり、自己解決してしまうことも多くなるのでお薦めでもあります。

    キャンセル

回答 1

checkベストアンサー

0

 注釈

まずはinitialStateを渡してRecipeListに反映させていです。

今回の質問の範囲を「初期表示が正常にできるまで」とした前提の上で、以下、回答となります。

※ 以前の回答は中途半端にstate更新部分の指摘も含んでおり、紛らわしくなるので削除しました。

 回答(編集版)

初期表示が上手くいかないという現象を再現する為に、
掲載コードを最小限に近い状態まで削ったコードが以下です。
※ エラーはそのまま残しています。

-> https://codesandbox.io/s/n3q7zr2v8l

// index.js
import React, { Component } from "react";
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore } from 'redux';

import RecipeList from "./RecipeList";
import rootReducer from './reducers';

const store = createStore(rootReducer);

class App extends Component {
  render() {
    return <RecipeList />;
  }
}

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);
// reducer.js
import { combineReducers } from "redux";

const initialState = {
  recipes: [
    { title: "白米", author: "Aさん" },
    { title: "玄米", author: "Bさん" }
  ]
};

const recipeReducer = (state = initialState) => {
  return state;
};

const rootReducer = combineReducers({
  recipes: recipeReducer
});

export default rootReducer;
// RecipeList.js
import React, { Component } from "react";
import { connect } from "react-redux";

class RecipeList extends Component {
  renderList() {
    return this.props.recipes.map(recipe => {
      return (
        <div>
          <p>{recipe.title}</p>
          <p>by {recipe.author}</p>
        </div>
      );
    });
  }

  render() {
    return <ul>{this.renderList()}</ul>;
  }
}

function mapStateToProps(state) {
  console.log("state.recipes", state.recipes);
  console.log("isArray", Array.isArray(state.recipes));
  console.log("state.recipes.map", state.recipes.map);
  console.log("{}.map", {}.map);
  console.log("[].map", [].map);

  return {
    recipes: state.recipes
  };
}

export default connect(mapStateToProps)(RecipeList);

このように余計なコードを削り落とすだけで、何が原因なのかが見えやすくなるのではないでしょうか?

1ができていない状態で動作確認もせず、その先の2、3に手を出し、そこで初めてエラーの存在に気づくような進め方だと、デバッグもその分、広範囲に及ぶことになり大変になるので、1つずつ着実に動くコードを積み上げるようにして下さい。

※現在の「redux-form Fieldに入力した内容をcontainerへ渡す方法」というタイトルの質問は、1も2もまだ出来ていないのに「3の部分が出来ないので教えて下さい」というような質問になってます。

一応、RecipeList.jsmapStateToProps関数内にconsole.logを差し込んでおいたので、「https://codesandbox.io/s/n3q7zr2v8l」のコンソール画面で、出力されるログを確認してみて下さい。その上で昨晩回答欄に追記した内容とログの結果、また、ご自身で書かれたrenderListメソッド内のコードを照らし合わせ、何を変えれば良いのかを考えてみて下さい。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/05/22 23:10

    const newState内が配列ではなく複数のオブジェクトになってしまう、ということでしょうか?
    理想はinitialStateの配列の最後に入力した内容を足していきたいです。

    簡易化してくださった例ですと
    const newState = { ...state.recipes, payload.recipes };
    ですか?

    キャンセル

  • 2018/05/22 23:10

    入れ違いですみません。追記確認しますので少々お待ち下さい。

    キャンセル

  • 2018/05/22 23:13

    食事に出てしまうので、ご自身で全体のコードと切り離した動作確認用のコードを書いて、動作確認を行ってみてください。

    キャンセル

  • 2018/05/23 01:17 編集

    投稿した回答は、とりあえず今回の質問に関係しそうな部分のコードのみにざっと目を通して回答をしたものなので、他にも修正すべき箇所はあるようですが、初期表示の問題に関する主な原因部分は指摘した通りだと思います。

    キャンセル

  • 2018/05/23 21:48

    回答が遅くなりすみません。
    昨晩アドバイスを頂いたとおり初期値を配列に変え、キー名を変更したところ初期値の表示は出来ましたので質問を閉じさせていただきます。

    質問文が不適切だった件について、不要ファイルは載せずにいましたが追記してくださったようにコードも削るものなのですね。タイトルと本文変更いたしました。
    独学で普段は人に質問をする機会も無いため、質問に不完全な部分があったことをお詫びいたします。

    キャンセル

  • 2018/05/23 22:16 編集

    このサイトに従わないといけない必須のルールというものは利用規約以外にはなく、コードを削るのは必須では勿論ないのですが、回答する側としては不要なコードはない方が助かります。

    ただし、人によっては真逆のことを言うかもしれないので、理想は必要最小限の現象を再現できるコードと、全部載せのコードの両方を載せることかもしれません。

    キャンセル

  • 2018/05/23 22:28 編集

    こちらの「質問のヒント 3-5」のアドバイス欄にかかれていることが上で述べた「不要なコードを削る」ことに関連しているので、参考になるかと思います。https://teratail.com/help/question-tips#questionTips3-5

    また、現象を再現する最小限のコードを用意することは、「https://teratail.com/help/question-tips#questionTips1-1」の「お願い」のところに書かれているような誤解を回避することにも繋がるかと思います。

    全体的に「質問のヒント」には良いことが書かれているので一通り読んでみることをお勧めします。

    ちなみに、Y-A-Aさんの質問はTeratailに投稿される質問の中では質問の質がだいぶ高い方だと思いので安心してください。情報不足な質問、何を言っているか伝わってこない質問がこのサイトは非常に多いので。

    キャンセル

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

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

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

  • React.js

    919questions

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

  • Redux

    129questions