Javascript 将react HOC与表单一起使用。使用HOC传递公共JSX和状态

Javascript 将react HOC与表单一起使用。使用HOC传递公共JSX和状态,javascript,reactjs,forms,state,higher-order-functions,Javascript,Reactjs,Forms,State,Higher Order Functions,我刚刚完成了一个相当大的项目,在react应用程序的不同部分使用了一个表单。表单在整个过程中是相同的,但是功能根据表单的使用位置而不同 因此,现在我有多个具有重复表单的组件。所有这些表单都是受控的,即(使用this.state…作为值)唯一的区别是呈现方法以及在某些按钮事件上表单数据发生了什么 我意识到这是一个可怕的编码,我真的想使用HOC使这些组件更加灵活和干净 这是其中一种形式,还有两种类似的形式 sampleForm = ( <form action="" n

我刚刚完成了一个相当大的项目,在react应用程序的不同部分使用了一个表单。表单在整个过程中是相同的,但是功能根据表单的使用位置而不同

因此,现在我有多个具有重复表单的组件。所有这些表单都是受控的,即(使用this.state…作为值)唯一的区别是呈现方法以及在某些按钮事件上表单数据发生了什么

我意识到这是一个可怕的编码,我真的想使用HOC使这些组件更加灵活和干净

这是其中一种形式,还有两种类似的形式

sampleForm = (
            <form action="" name="sample">
                <div className="group">
                    <label htmlFor="">Descriptive Name:</label>
                    <input type="text" name="name" value={this.state.name}
                        onChange={this.handleChange} placeholder="Descriptive Name" />
                </div>
                <div className="group">
                    <label>Sample Codename:</label>
                    <input type="text" name="codeName" value={this.state.codeName}
                        onChange={this.handleChange} placeholder="Ex: MM_MG_01" />
                </div>
                <div className="group">
                    <label htmlFor="">GPS Coordinates:</label>
                    <input type="text" name="coords" value={this.state.coords}
                        onChange={this.handleChange} placeholder="GPS Coordinates" />
                </div>
                <div className="group">
                    <label htmlFor="">Metagenomic Data:</label>
                    <textarea type="text" name="METAdesc" value= 
                     {this.state.METAdesc}
                        onChange={this.handleChange} placeholder="Image Description" rows={7} />
                    <input type="file" name="METAimage"
                        onChange={this.handleChange} />
                </div>
                {notes}
            </form>
        )
sampleForm=(
描述性名称:
示例代码名:
GPS坐标:
宏基因组数据:
{notes}
)
我目前在render方法中复制了这三个(四次:/)


如何将这三个组件传递到下一个组件

高阶组分是一种反应模式,其中:

函数接受一个组件并返回一个新组件。

一个表单可以为一个表单做的事情是管理状态,处理事件如<代码> OnChchange < /COD>和<代码> OnSudio等。因此,考虑一个<代码>表单< /C>组件作为一个功能组件,作为一个参数传递给您的<代码>窗体处理程序< /Cord>HOO.

比如说,

FormHandler.js中的

const withFormHandling = FormComponent => class extends Component {/* Component Logic */}
export default withFormHandling
import withFormHandling from './path/to/Components/FormHandler'
const Form = props => {/* Component Logic */}
export default withFormHanlding(Form);
Form.js中的

const withFormHandling = FormComponent => class extends Component {/* Component Logic */}
export default withFormHandling
import withFormHandling from './path/to/Components/FormHandler'
const Form = props => {/* Component Logic */}
export default withFormHanlding(Form);
那么,我们如何处理多个不同表单的表单细节、道具和状态

  • 确定每个表单应该具有的状态或道具
在您的情况下,可能会出现以下情况:

formAction
formName
handleChange
handleSubmit
inputNames
notes
errors

我会考虑传递<代码>输入名称<代码>和<代码>错误<代码>作为道具(它们应该在结构上匹配)。你可以在这里增加各种各样的复杂性,或者保持简单。就我个人而言,我在我的状态中保留了一个

字段
对象和一个
错误
对象,两者都有匹配的键。一个用于维护用户输入的值,另一个用于存储字段验证结果

然后让我们填写我们的表格

const withFormHandling = FormComponent => class extends Component {
    constructor(props) {
        super(props)
        this.state = {
            fields: {...props.inputNames},
            errors: {...props.errors},
            selectedFile: null
        }
        this.handleChange = this.handleChange.bind(this);
        this.handleFile = this.handleFile.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }
    // https://codeburst.io/save-the-zombies-how-to-add-state-and-lifecycle-methods-to-stateless-react-components-1a996513866d 
    static get name() {
        return Component.name;
    }

    handleChange(e) {
        const target = e.target;
        let value = target.type === 'checkbox' ? target.checked : target.value;
        let name = target.name;
        const fields = {...this.state.fields},  errors = {...this.state.errors};
        const error = //create a validation function that returns an error based on field name and value
        fields[name] = value;
        errors[name] = error;
        this.setState({ fields, errors })
    }

    handleFile(e) {
        this.setState({selectedFile: event.target.files[0]})
    }

    handleSubmit(e) {
        //validate form
        //flatten fields into structure of data for form submission
        //handle submission of data and also file data
    }

    render() {
        return <FormComponent 
                   {...this.props} //to access form specific props not handled by state
                   fields={this.state.fields}
                   errors={this.state.errors}
                   handleChange={this.handleChange}
                   handleFile={this.handleFile}
                   handleSubmit={this.handleSubmit}
               />
    }
}
export default withFormHandling
最后,在其他一些组件中,您可以随时调用
表单
组件,传递独特的道具

//...some other Component Render Method

// form one, with its own internal state managed by HOC
<Form formAction={'https://someendpoint1'} formName={"some form 1"} inputNames={{name:'', codename:''}} errors={{name:'', codename:''}} notes={"some notes 1"}/>

// form two, with its own internal state managed by HOC
<Form formAction={'https://someendpoint2'} formName={"some form 2"} inputNames={{name:'', codename:''}} errors={{name:'', codename:''}} notes={"some notes 2"}/>

// form three, with its own internal state managed by HOC
<Form formAction={'https://someendpoint3'} formName={"some form 3"} inputNames={{name:'', codename:''}} errors={{name:'', codename:''}} notes={"some notes 3"}/>
/…其他一些组件渲染方法
//表单一,其自身的内部状态由HOC管理
//形式二,内部状态由HOC管理
//表三,其内部状态由HOC管理
这就是我处理一个应用程序的方式,它有许多不同的表单,具有相似的结构


另一个要考虑的模式是代码>渲染道具< /代码>,但是我将把它留给另一个问题和另一个回答者。< / P>你有三个相同的形式?相同的字段/值/事件处理程序?没有两个不同的表单和bothI中的一个notes表单最近构建了一个管理门户,其中有十几个表单由HOC管理。密钥正确处理道具,然后在onChange和onSubmit处理程序中具有一些条件。也许我们可以聊聊,因为我的代码是公司内部代码。