redux表单动态类别

时间:2018-04-25 23:01:26

标签: reactjs redux redux-form

我正在使用redux表单,我在这里做的是当用户选择类别时,下一个选择字段应该具有所有子类别,具体取决于所选择的类别。

我所做的是我创建了api来获取所有类别,我通过componentWillMount触发动作并加载第一类选择字段中的所有类别,然后我使用redux-form的formValueSelector将所选类别添加到state / this.props,然后我使用componentWillReceiveProps()来触发获取子类别,例如“this.props.categoryId”,我使用formValueSelector进行状态并且有效。

我的问题是,这是正确的aporoach,还有更好的方法吗? 第二个问题是,如何将categoryChildId字段重置为,当categoryId字段更改时,让我们说空白?

import React from 'react';
import moment from 'moment';
import { Field, reduxForm, formValueSelector } from 'redux-form';
import { connect } from 'react-redux';
import { Link, NavLink } from 'react-router-dom';
import {CopyToClipboard} from 'react-copy-to-clipboard';
import * as actions from '../../actions/category';

const renderField = ({ input, label, type, meta: { touched, error } }) => (
  <div>
    <input {...input} placeholder={label} type={type} />
    {touched &&
     error &&
     <div className="error">{error}</div>}
  </div>
)

const renderTextArea = ({ input, label, type, meta: { touched, error } }) => (
  <div>
    <textarea {...input} placeholder={label} type={type} />
    {touched &&
     error &&
     <div className="error">{error}</div>}
  </div>
)

class AddProduct extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: `${process.env.SITE_URL}/user/${props.user.username}`,
      copied: false,
      isLoading: false
    };
  }

  componentWillMount() {
     this.props.startSetCategories()
  }

  componentWillReceiveProps(nextProps) {
      this.props.startSetCategoryChildren(nextProps.categoryId)
      console.log(nextProps)
  }

  renderCategorySelector = ({ input, meta: { touched, error } }) => {
    return (
      <div>
        <select {...input}>
          <option value="">select category</option>
          {!this.props.categories ? (
            <option value="">loading...</option>
          ) : (
            this.props.categories.map(category => <option value={category._id} key={category._id}>{category.name}</option>)
          )
        }
        </select>
        {touched && error && <span>{error}</span>}
      </div>
    )
  }

  renderCategoryChildSelector = ({ input, meta: { touched, error } }) => {
    return (
      <div>
        <select {...input}>
          <option value="">select sub category</option>
          {!this.props.categoryChildren ? (
            <option value="">loading...</option>
          ) : (
            this.props.categoryChildren.categoryChildren.map(categoryChild => <option value={categoryChild._id} key={categoryChild._id}>{categoryChild.name}</option>)
          )
          }
        </select>
        {touched && error && <span>{error}</span>}
      </div>
    )
  }

  submitForm = values => {
    console.log(values)

  }

  render() {
    const username = localStorage.getItem('username');
    const { user } = this.props;
    const { handleSubmit, pristine, submitting, categoryId } = this.props;

    return (
      <div className="profile-wrapper">
        <div className="profile">
          <form className="profile-addproduct-left" onSubmit={handleSubmit(this.submitForm.bind(this))}>
            <div className="profile-addproduct-title">
              <h2>New Product</h2>
              <p>Fill out the form.</p>
            </div>
            <div className="profile-form-group">
              <div className="profile-form-item">
                <p>Title</p>
                <Field
                  name="title"
                  type="text"
                  label="title of a product"
                  component={renderField}
                />
              </div>
              <div className="profile-form-item">
                <p>Category</p>
                <Field
                  name="categoryId"
                  type="text"
                  component={this.renderCategorySelector}
                  label="category"
                />
                {this.props.categoryId ?
                  <Field
                    name="categoryChildId"
                    type="text"
                    component={this.renderCategoryChildSelector}
                    label="categoryChild"
                  /> :
                  ''
                }
              </div>


              <div className="profile-form-item">
                <p>Description</p>
                <Field
                  name="description"
                  type="text"
                  label="Write some interesting..."
                  component={renderTextArea}
                />
              </div>


            </div>
            <div className="profile-addproduct-form-submit">
              <button className="button button--register" type="submit" disabled={this.state.isLoading || pristine}>Submit New Product</button>
            </div>
          </form>


        </div>
      </div>
    )
  }
};


AddProduct =  reduxForm({
  form: 'addproduct-form'
})(AddProduct)

const selector = formValueSelector('addproduct-form')

AddProduct = connect(state => {
  const categoryId = selector(state, 'categoryId')
  return {
    categoryId,
    categories: state.category.categories,
    categoryChildren: state.category.categoryChildren
  }
}, actions)(AddProduct)

export default AddProduct

1 个答案:

答案 0 :(得分:1)

你不应该在startSetCategoryChildren中调用componentWillReceiveProps(或任何其他api)...因为每当componentWillReceiveProps调用

时它都会调用
componentWillReceiveProps(nextProps) {
  this.props.startSetCategoryChildren(nextProps.categoryId)
  console.log(nextProps)
}

您可以在handleChange

Field上执行此操作
            <Field
              name="categoryId"
              type="text"
              component={this.renderCategorySelector}
              label="category"
              onChange={(e) => this.props.startSetCategoryChildren(e.target.value)}
            />