代码之家  ›  专栏  ›  技术社区  ›  obsidian

redux表单动态类别

  •  1
  • obsidian  · 技术社区  · 6 年前

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

    我所做的是创建了用于获取所有类别的api,我通过componentWillMount触发操作,并在第一个categories select字段中加载所有类别,然后使用redux表单的formValueSelector将所选类别设置为状态/this。props,然后我使用componentWillReceiveProps()触发获取子类别,例如“this.props.categoryId”,我用formValueSelector声明了该子类别,并且该子类别有效。

    我的问题是,这是对的吗?有没有更好的方法? 第二个问题是,如何将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 回复  |  直到 6 年前
        1
  •  1
  •   Ashh    6 年前

    你不应该打电话给 startSetCategoryChildren (或任何其他api) componentWillReceiveProps 。。。因为每当调用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)}
                />