我有很长的反应。以前,它有一堆定义如下的组件:
<input
type='text'
value={this.state.form.nameOfFormField}
onChange={this.updateForm('nameOfFormField')} />
其中updateForm
是(field) => (e) => {}
形式的函数,可以更轻松地重用代码。
我想让这更容易维护,所以我创建了一个组件SpecialInput
,其定义如下:
const SpecialInputBuilder = (form, onChange) => ({ field, ..props }) => (
<input
type='text'
value={form[field]}
onChange={onChange(field)}
{...props} />
)
现在,我可以在渲染过程中定义输入,如下所示:
const SpecialInput = SpecialInputBuilder(this.state.form, this.updateForm)
并在像这样的组件中使用它:
<SpecialInput field='nameOfFormField' />
显然,这更加简洁。但这也意味着每次输入字段时输入字段都会丢失焦点(即调用updateForm
时),因为每次SpecialInput
函数都定义render
时调用。为每个元素定义key
似乎根本不能解决问题。如何在使用这个更简单的组件时解决这个问题?有中间立场吗?
答案 0 :(得分:1)
为什么不将输入构建器更改为反应组件?
const SpecialInput = (props) => {
return (
<input
value={props.form[props.field]}
{...props}
type={props.type || 'text'}
onChange={() => props.onChange(props.field)}
/>
)
}
并以同样的方式使用它。
<SpecialInput field='nameOfFormField' onChange={this.updateForm} form={this.state.form} />
答案 1 :(得分:0)
主要问题是,onChange
调用在呈现时立即执行,而不是在输入更改时调用要调用的函数。
// this executes immediately
onChange={onChange(field)}
// this is a reference to the function with a prop prepended
onChange={onChange.bind(this,field)}
答案 2 :(得分:0)
我有一个类似的方法,但最终改为此;
(1)输入typer子组件:
import React, { Component } from 'react';
class FreeTextField extends Component {
inputValueFn(e) {
this.props.userInput(this.props.responseObject, e.target.value);
}
render() {
return (
<div className="input-group">
<label>{this.props.buttonText ? this.props.buttonText : "Firstname"}</label>
<input type={this.props.type} placeholder="" className="form-control" defaultValue={this.props.defaultValue} onChange={this.inputValueFn.bind(this)} />
</div>
);
}
}
export default FreeTextField;
(2)从父组件中,您可以通过道具指定所有相关儿童attr
// import
import FreeTextField from './pathTo/FreeTextField';
// Initial state
this.state = {
responseObject: {}
}
// onChange it updates the responseObject
userInput(fieldKey,value) {
let responseObject = this.state.responseObject;
responseObject[fieldKey] = value;
this.setState({responseObject:responseObject});
}
// component render()
<FreeTextField
buttonText="First Name"
type="text"
formObjectKey="first_name"
userInput{this.userInput.bind(this)} />