Javascript 以Redux形式动态加载初始值

Javascript 以Redux形式动态加载初始值,javascript,reactjs,redux,redux-form,Javascript,Reactjs,Redux,Redux Form,以Redux表单为例,我试图动态地设置它。这是为了编辑书籍列表中的特定书籍,并使用在express.js中设置的简单api 满的容器在下面。我需要在mapstatetops函数中传入initialValues。在本例中,它是通过一个静态对象完成的,但我不知道如何使用通过fetchBook拉入的信息,并将其传递给initialValues 容器: import React, { Component, PropTypes } from 'react'; import { reduxForm } fr

以Redux表单为例,我试图动态地设置它。这是为了编辑书籍列表中的特定书籍,并使用在express.js中设置的简单api

满的容器在下面。我需要在
mapstatetops
函数中传入
initialValues
。在本例中,它是通过一个静态对象完成的,但我不知道如何使用通过
fetchBook
拉入的信息,并将其传递给
initialValues

容器:

import React, { Component, PropTypes } from 'react';
import { reduxForm } from 'redux-form';
import { connect } from 'react-redux';
import { Link } from 'react-router';
import { fetchBook, editBook } from '../actions/index';

class BookEdit extends Component {

  componentWillMount() {
      this.props.fetchBook(this.props.params.id);
  }

    static contextTypes = {
    router: PropTypes.object
    }

  onSubmit(props) {
    this.props.editBook(this.props.book.id, props)
      .then(() => {
        this.context.router.push('/');
      });
  }

    const data = {
        title: {this.props.book.title},
        description: {this.props.author}
    }

  render() {

    const { fields: { title, author }, handleSubmit } = this.props;
    const { book } = this.props;

    if (!book) {
      return (
          <div>
            <p>Loading...</p>
          </div>
      )
    }

    return (
      <div>
      <Link to="/">Back</Link>
        <form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
                <h2>Add a new book</h2>

                <label>Title</label>
                <input type="text" {...title} />
                <div className="text-help">{title.touched ? title.error : ''}</div>

                <label>Author</label>
                <input type="text" {...author} />
                <div className="text-help">{author.touched ? author.error : ''}</div>

                <button type="submit">Add</button>
                <Link to="/" className="button">Go back</Link>
            </form>
      </div>
    );
  }
}

function mapStateToProps(state) {
  return {
      book: state.books.book,
      initialValues: // how do I pass in the books here?
  };
}

export default reduxForm({
  form: 'EditBookForm',
  fields: ['title', 'author']
}, mapStateToProps, { fetchBook, editBook })(BookEdit);
import React,{Component,PropTypes}来自'React';
从'redux form'导入{reduxForm};
从'react redux'导入{connect};
从“反应路由器”导入{Link};
从“../actions/index”导入{fetchBook,editBook};
类BookEdit扩展组件{
组件willmount(){
this.props.fetchBook(this.props.params.id);
}
静态上下文类型={
路由器:PropTypes.object
}
提交(道具){
this.props.editBook(this.props.book.id,props)
.然后(()=>{
this.context.router.push('/');
});
}
常数数据={
标题:{this.props.book.title},
描述:{this.props.author}
}
render(){
const{fields:{title,author},handleSubmit}=this.props;
const{book}=this.props;
如果(!书本){
返回(
加载

) } 返回( 返回 添加一本新书 标题 {title.touch?title.error:'} 作者 {author.touch?author.error:'} 添加 回去 ); } } 函数MapStateTops(状态){ 返回{ 书:state.books.book, initialValues://我如何在这里过账? }; } 导出默认reduxForm({ 表格:'EditBookForm', 字段:[“标题”、“作者”] },mapstatetops,{fetchBook,editBook}(BookEdit);

谢谢。

您的表单值不是
状态中的值。books.book
?我想这就是你想要的:

function mapStateToProps(state) {
  return {
      book: state.books.book,
      initialValues: state.books.book
  };
}
由于您只需要查看
this.props.book
,以了解它是否已加载,因此可以更明确地执行以下操作:

function mapStateToProps(state) {
  return {
      loaded: !!state.books.book,
      initialValues: state.books.book
  };
}

希望能有所帮助。

关于上述问题,埃里克。我有下面的表格,不知道为什么在提交时没有验证。它将数据加载到字段中,但当我点击提交时,验证失败

表单_Bayan.js

import React,{Component,PropTypes}来自“React”;
从“react router”导入{browserHistory};
从“redux表单”导入{reduxForm,Field};
从“/”表单\字段\组件”导入{MyCustomInput、MyImpleInput、MyCustomSelect};
从“react redux”导入{connect};
从“redux”导入{bindActionCreators};
进口{
管理员获取自动建议,
行政建议法案,
管理生成插件,
行政许可法案,
管理员_GETCATID _BYNAME _Lbl,
《行政法典》,
行政管理,
行政新巴亚安法,
行政法,
行政法
}来自“../../actions/adminActionCreators”;
从“洛达斯”进口;
类NewBayanForm扩展组件{
建造师(道具){
super(props);//此组件通过用于重定向的props继承“toggleViewFunction”函数
this.generateSlug=this.generateSlug.bind(this);
此.state={
submitButtonMeta:{
btnTitle:“保存”,
btn类:“btn btn默认值”,
btnIcon:null,
禁用:false
},
globalMessage:{//由ActionCreation+Reducer执行操作并返回消息时设置
消息:“”,
类名:“
},
临时数据:{
//_bayaansMainCat_id:1,//“1”指管理中的“Bayaans”父类别,此id用于不同类型的查找,即获取autosuggest的可用子类别,按父类别下的名称获取cat id
_bayaansMainCat_id:this.props.associatedMainCatId,//从父组件传递到避免冗余声明
_autoSuggestCatList:[],
鼻涕虫:“,
_catId:null
}
};
}
resetMessageState(){
var noMsg={message:,className:};
this.setState({globalMessage:noMsg});
}
componentDidMount(){
log(“(componentDidMount)”);
this.props.adminFetchAutoSuggestCats_act(this.state.tempData.the_bayaansMainCat_id);
}
道具(道具){
//console.log(“----提交表单------”);
//控制台日志(道具);
此.disableSubmitButton();
//为提交请求准备数据
//项目标题、项目片段、内容、图片、附件、媒体路径、参考、标记关键字、作者姓名、类别id、创建日期
var newBayanObj={
项目名称:props.titleTxt,
项_slug:this.state.tempData.slug,
内容:props.videoIdTxt,
图片:“,
附件:“,
媒体路径:“https://www.youtube.com/watch?v=“+props.videoIdTxt,
参考号:“,
tag_关键字:props.keywordsText,
作者名称:props.authorTxt,
cat_id:this.state.tempData.the_catId
};
这个.props.adminUpdateBayaan_法案(Newbayanobj)
.然后(()=>{
console.log(“%c(doSubmit)更新的bayaan,重新绘制更新的bayaan列表…”,“颜色:蓝色;字体重量:粗体;”);
this.props.adminifetchArticlesBycat_act(this.props.associatedMainCatId)
.然后(()=>{
console.log(“%c(doSubmit)重定向)
import React, {Component, PropTypes} from "react";  
import {browserHistory} from "react-router";        
import {reduxForm, Field} from "redux-form";

import {MyCustomInput, MySimpleInput, MyCustomSelect} from "./__form_field_components";

import {connect} from "react-redux";
import {bindActionCreators} from "redux";
import {
    ADMIN_FETCH_AUTOSUGGESTS_Lbl,
    adminFetchAutoSuggestCats_act,
    ADMIN_GENERATESLUG_Lbl,
    adminGenerateSlug_act,
    ADMIN_GETCATID_BYNAME_Lbl,
    adminGetCatIdByName_act,
    ADMIN_ADDNEWBAYAAN_Lbl,
    adminAddNewBayaan_act,
    adminFetchArticlesByCat_act,
    adminUpdateBayaan_act
} from "../../actions/adminActionCreators";
import _ from "lodash";


class NewBayanForm extends Component {

    constructor(props) {
        super(props);       // this component inherits "toggleViewFunction" function through props for redirection

        this.generateSlug = this.generateSlug.bind(this);

        this.state = {
            submitButtonMeta: {
                btnTitle: "Save",
                btnClass: "btn btn-default",
                btnIcon: null,
                disabled: false
            },
            globalMessage: {                        // set when an action is performed by ActionCreation+Reducer and a message is returned
                message: "",
                className: ""
            },
            tempData: {
                //the_bayaansMainCat_id : 1,                // '1' refers to the 'Bayaans' parent category in admin , this ID is used here for different sort of lookups i.e. fetch available subcats for autosuggest, fetch cat ID by name under parent catID
                the_bayaansMainCat_id: this.props.associatedMainCatId,              // being passed from parent component to avoide redundent declaration
                the_autoSuggestCatList: [],
                slug: "",
                the_catId: null
            }
        };
    }

    resetMessageState() {
        var noMsg = {message: "", className: ""};
        this.setState({globalMessage: noMsg});
    }

    componentDidMount() {
        console.log("<NewBayanForm> (componentDidMount)");
        this.props.adminFetchAutoSuggestCats_act(this.state.tempData.the_bayaansMainCat_id);
    }

    doSubmit(props) {
        //console.log("----- submitting form -----");
        //console.log(props);
        this.disableSubmitButton();
        // prepare data for submit request
        // item_title, item_slug, content, picture, attachment, media_path, reference, tag_keywords, author_name, cat_id, date_created
        var newBayanObj = {
            item_title: props.titleTxt,
            item_slug: this.state.tempData.slug,
            content: props.videoIdTxt,
            picture: "",
            attachment: "",
            media_path: "https://www.youtube.com/watch?v=" + props.videoIdTxt,
            reference: "",
            tag_keywords: props.keywordsTxt,
            author_name: props.authorTxt,
            cat_id: this.state.tempData.the_catId
        };


            this.props.adminUpdateBayaan_act(newBayaanObj)
                .then(() => {
                    console.log("%c <NewBayanForm> (doSubmit) Updated bayaan, refetching updated bayaans list...", "color:blue;font-weight:bold;");
                    this.props.adminFetchArticlesByCat_act(this.props.associatedMainCatId)
                        .then(() => {
                            console.log("%c <NewBayanForm> (doSubmit) Redirecting to Gallery after update...", "color:blue;font-weight:bold;");
                            this.props.toggleViewFunction();        // comming from Parent Class (bayaansPage)
                        });
                });


    }

    disableSubmitButton() {
        console.log("<NewBayanForm> (disableSubmitButton)");
        // Ref: http://stackoverflow.com/questions/18933985/this-setstate-isnt-merging-states-as-i-would-expect
        var newButtonState = {
            btnTitle: "Please wait... ",
            btnClass: "btn btn-disabled",
            btnIcon: null,
            disabled: true
        };
        this.setState({submitButtonMeta: newButtonState});
        this.resetMessageState();           // Need to reset message state when retrying for form submit after 1st failure
    }

    enableSubmitButton() {
        console.log("<NewBayanForm> (enableSubmitButton)");
        // Ref: http://stackoverflow.com/questions/18933985/this-setstate-isnt-merging-states-as-i-would-expect
        var newButtonState = {btnTitle: "Save", btnClass: "btn btn-default", btnIcon: null, disabled: false};
        this.setState({submitButtonMeta: newButtonState});
    }


    fetchCategoryId(value) {
        console.log('<NewBayanForm> (fetchCategoryId) input-Value:', value);                // make API call to fetch / generate category ID for this post
        this.props.adminGetCatIdByName_act(value, this.state.tempData.the_bayaansMainCat_id);               // '1': refers to look up under 'Bayaans' parent category for the specified category name
    }

    // will always receive and triggers when there are 'new props' and not old/same props
    componentWillReceiveProps(nextProps) {                      // required when props are passed/changed from parent source. And we want to do some operation as props are changed (Ref: http://stackoverflow.com/questions/32414308/updating-state-on-props-change-in-react-form)
        console.log("<NewBayanForm> (componentWillReceiveProps) nextProps: ", nextProps);       // OK
        //console.log("this.props : ", this.props); // OK
        //console.log("nextProps.siteEssentials.actionsResult : ", nextProps.siteEssentials.actionsResult); // OK
        if (nextProps.hasOwnProperty("siteEssentials")) {       // if action status appeared as Done!
            if (nextProps.siteEssentials.hasOwnProperty("actionsResult")) {     // if action status appeared as Done!



                if (nextProps.siteEssentials.actionsResult[ADMIN_GETCATID_BYNAME_Lbl] !== "FAILED") {
                    var clonedState = this.state.tempData;
                    clonedState.the_catId = nextProps.siteEssentials.actionsResult[ADMIN_GETCATID_BYNAME_Lbl];
                    //var   newTempState = {slug: this.state.tempData.slug, the_catId: nextProps.siteEssentials.actionsResult[ADMIN_GETCATID_BYNAME_Lbl] };
                    this.setState({tempData: clonedState});
                }

                if (nextProps.siteEssentials.actionsResult[ADMIN_FETCH_AUTOSUGGESTS_Lbl] !== "FAILED") {
                    var clonedState = this.state.tempData;
                    clonedState.the_autoSuggestCatList = nextProps.siteEssentials.actionsResult[ADMIN_FETCH_AUTOSUGGESTS_Lbl];
                    this.setState({tempData: clonedState});
                }
                console.log("<NewBayanForm> (componentWillReceiveProps) new-State:", this.state);

            }
        }
    }


    render() {    // rendering Edit form
        const {handleSubmit} = this.props;
        console.log('<NewBayanForm> (render_editForm) this.props:', this.props);
        return (
            <div className="adminForm">
                <form onSubmit={handleSubmit(this.doSubmit.bind(this))}>
                    <div className="col-sm-6">
                        <div className="row">
                            <div className="col-sm-5"><label>Title:</label></div>
                            <div className="col-sm-7"><Field name="titleTxt" component={MySimpleInput}
                                                             defaultValue={this.props.name} type="text"
                                                             placeholder="Enter Title"/></div>
                        </div>
                        <div className="row">
                            <div className="col-sm-5"><label>Slug:</label></div>
                            <div className="col-sm-7">{this.state.tempData.slug || this.props.slug} <input
                                type="hidden" name="slugTxt" value={this.state.tempData.slug}/></div>
                        </div>
                        <div className="row">
                            <div className="col-sm-5"><label>Select Category:</label></div>
                            <div className="col-sm-7"><Field name="catTxt" component={MyCustomSelect}
                                                             defaultValue={this.props.category_name} type="text"
                                                             placeholder="Select or Type a New"
                                                             selectableOptionsList={this.state.tempData.the_autoSuggestCatList}
                                                             onSelectionDone={ this.fetchCategoryId.bind(this) }/>
                                <input type="hidden" name="catIdTxt"
                                       value={this.state.tempData.the_catId || this.props.category_id}/>
                            </div>
                        </div>
                    </div>
                    <div className="col-sm-6">
                        <div className="row">
                            <div className="col-sm-5"><label>Youtube Video ID:</label></div>
                            <div className="col-sm-7"><Field name="videoIdTxt" component={MySimpleInput}
                                                             defaultValue={this.props.content} type="text"
                                                             placeholder="TsQs9aDKwrw"/></div>
                            <div className="col-sm-12 hint"><b>Hint: </b> https://www.youtube.com/watch?v=<span
                                className="highlight">TsQs9aDKwrw</span></div>
                        </div>
                        <div className="row">
                            <div className="col-sm-5"><label>Author/Speaker:</label></div>
                            <div className="col-sm-7"><Field name="authorTxt" component={MySimpleInput}
                                                             defaultValue={this.props.author} type="text"/></div>
                        </div>
                        <div className="row">
                            <div className="col-sm-5"><label>Tags/Keywords:</label></div>
                            <div className="col-sm-7"><Field name="keywordsTxt" component={MySimpleInput}
                                                             defaultValue={this.props.tag_keywords} type="text"/>
                            </div>
                        </div>
                    </div>
                    <div className="row">
                        <div className={this.state.globalMessage.className}>{this.state.globalMessage.message}</div>
                    </div>
                    <div className="buttonControls">
                        <a className="cancelBtn" onClick={this.props.toggleViewFunction}>Cancel</a>
                        <button className={this.state.submitButtonMeta.btnClass}
                                disabled={this.state.submitButtonMeta.disabled}>
                            {this.state.submitButtonMeta.btnTitle}</button>
                    </div>
                </form>
            </div>
        );
    }


}

function validate(values) { // Validate function being called on Blur
    const errors = {};
    if (!values.titleTxt)
        errors.titleTxt = "Enter Title";
    if (!values.catTxt)
        errors.catTxt = "Select/Enter a Category";
    if (!values.videoIdTxt)
        errors.videoIdTxt = "Enter youtube video ID (follow the provided hint)";
    if (!values.keywordsTxt)
        errors.keywordsTxt = "Enter keywords (will help in search)";


    return errors;
}


// ReduxForm decorator 
const newBayanFormAdmin_reduxformObj = reduxForm({
    form: "newBayanFormAdmin",  // any unique name of our form
    validate                // totally equivelent to-->  validate: validate
});


function mapStateToProps({siteEssentials}, ownProps) {
    console.log("<NewBayanForm> (mapStateToProps) siteEssentials:", siteEssentials);
    // 1st param is related to our Redux State, 2nd param relates to our own component props
    var initialValues = {
        titleTxt: ownProps.name,
        slugTxt: ownProps.slug,
        catTxt: ownProps.category_name,
        catIdTxt: ownProps.category_id,
        videoIdTxt: ownProps.content,
        authorTxt: ownProps.author,
        keywordsTxt: ownProps.tag_keywords
    };
    console.log("<NewBayanForm> (mapStateToProps) initialValues: ", initialValues);
    return ({siteEssentials}, initialValues);
};

function mapDispatchToProps(dispatch) {
    return bindActionCreators({
        adminFetchAutoSuggestCats_act,
        adminGenerateSlug_act,
        adminGetCatIdByName_act,
        adminAddNewBayaan_act,
        adminFetchArticlesByCat_act
    }, dispatch);
};


NewBayanForm = connect(mapStateToProps, mapDispatchToProps) (newBayanFormAdmin_reduxformObj(NewBayanForm));

export default NewBayanForm;