反应自定义控制的表单组件事件

时间:2017-09-29 16:33:06

标签: reactjs

当我们使用内置HTML输入组件时,onChange侦听器被赋予SyntheticEvent的实例,这允许我们执行类似

的操作
onChange = (event) => {
  this.setState({
    [event.target.name]: event.target.value
  })
};

render() {
  return (
    <div>
      <input 
        type="text" 
        name="username" 
        value={ this.state.username }
        onChange={ this.onChange } />

      <input 
        type="password" 
        name="password" 
        value={ this.state.password }
        onChange={ this.onChange } />
    </div>
  );
}

请注意,我可以为多个表单控件使用相同的侦听器。但是,如果我们使用自定义表单控件,比如DatePicker或更像特定于域的UserSelector,这些组件通常都有自己的API来处理更改(例如onChange(newValue)onChange(oldValue, newValue))。这迫使我为每个字段写一个监听器。

有没有好办法处理这种情况?

1 个答案:

答案 0 :(得分:2)

一种方法是构造自己的数据结构以发出类似于事件的信号。

import React, { PureComponent } from 'react';

const onChange = component => event => {
  component.props.onChange({
    target: {
      value: Object.assign({}, component.props.value, {
        [event.target.name]: event.target.value,
      })
    }
  })
};

export default class UserControl extends PureComponent {
  render () {
    return (
      <div>
        <input name="name" value={this.props.value.name} onChange={onChange(this)} />
        <input name="age" value={this.props.value.age} onChange={onChange(this)} />
      </div>
    );
  }
};

您的自定义事件对象可以根据需要选择React合成事件的其他键。

请注意,onChange处理程序不必绑定到类。由于它是通用的,因此可以作为单独的一部分代码存在,该代码首先接受组件。

编辑:要考虑的一件事是在需要时也传递stopPropagation方法。我还没有自己做,但这似乎行得通。注意event.persist()。这样可以确保React不重用SyntheticEvent。

const onChange = component => event => {
  event.persist();
  component.props.onChange({
    stopPropagation: event.stopPropagation.bind(event),
    target: {
      value: Object.assign({}, component.props.value, {
        [event.target.name]: event.target.value
      })
    }
  });
};