如何动态渲染表单字段(未预定义)以在React.js中获取受控字段

时间:2019-05-15 11:01:31

标签: reactjs state controlled-component

我的问题是: 我在React中非常新鲜,我必须基于CMS的数据来呈现表单,这允许用户将表单字段放置在网格中,这使得JSON结构相当复杂。

我希望表单域成为表单的受控组件,我正在寻找最干净的解决方案。

当前解决方案的问题之一是setState的异步性导致字段的初始值不确定。

我添加了“渲染”状态属性,以使由字段更新引起的初始渲染和重新渲染之间有所不同,但这是肮脏的技巧,而不是解决方案。

class Forms extends React.Component<any, any> {
  constructor(props: any) {
    super(props);
  }

  state = { rendering: true, fields: [] }

  shouldComponentUpdate(nextProps, nextState) {
    return !this.state.rendering || this.props !== nextProps;
  }

  onChange = (e) => {
    const { target } = e;
    const value = target.type === 'checkbox' ? target.checked : target.value;
    this.setState({ [target.name]: value });
  }

  renderFormComponents = (props) => {
    const fields = [];
    const { components, pageId } = props;
    const renderedComponents = components.map((component, index) => {
      const componentId = component.value.value.guid;

      if (this.state.rendering) {
        this.setState({ [componentId]: "" });
      }
      fields.push(componentId);
      return <FormInput key={componentId} {...component.value.value} value={this.state[componentId]} onChange={this.onChange} />;
    });

    if (this.state.rendering) {
      this.setState({ fields, rendering: false });
    }

    return renderedComponents;
  };

  render() {
    return (
      <ContentGrid
        sections={this.props.value.sections}
        componentType="form-grid"
        pageId={this.props.pageId}
        customRenderComponents={this.renderFormComponents}
      />
    );
  }
}

工作示例在这里:https://codepen.io/ttanathoss/project/editor/DQGzzn

ContentGrid组件正在其他地方使用,所以我不想通过它传递很多不必要的日期。

还有一件事是我必须向表单添加验证,并且每个字段都可以定义自己的规则。我当时在考虑在字段级别定义的验证方法,而不是在窗体级别定义的formValidation方法调用每个字段验证,但我想不出如何正确实现它。

0 个答案:

没有答案