我的问题是: 我在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方法调用每个字段验证,但我想不出如何正确实现它。