Handling submit in React/Redux form

2019-05-11 23:23发布

问题:

I want to capture the form values when a user submits a form. The React tutorial shows this:

var CommentForm = React.createClass({
  handleAuthorChange: function(e) {
    this.setState({author: e.target.value});
  },
  handleTextChange: function(e) {
    this.setState({text: e.target.value});
  },
  handleSubmit: function(e) {
    e.preventDefault();
    var author = this.state.author.trim();
    var text = this.state.text.trim();
    if (!text || !author) {
      return;
    }
  render: function() {
    return (
      <form className="commentForm" onSubmit={this.handleSubmit}>

This style pushes all changes into state via a handling function per input. If I were to go full on with Redux, I believe I would add actions and action creators to the mix, which seems like a lot of overhead.

Note the argument to handleSubmit is an event.

I came across a following React/Redux starter kit which looks to be much easier to work with. It uses a smart/container component and dumb/presentational component combination:

Container

@connect(
  () => ({}),
  {initialize})
export default class Survey extends Component {
  ...

  handleSubmit = (data) => {
    window.alert('Data submitted! ' + JSON.stringify(data));
    this.props.initialize('survey', {});
  }

  render()
    return ( <SurveyForm onSubmit={this.handleSubmit}/> )
  ...

Presentational

class SurveyForm extends Component {
  static propTypes = {
    handleSubmit: PropTypes.func.isRequired,
  }

  render() {
    const { handleSubmit } = this.props;
    return (
      <div>
        <form className="form-horizontal" onSubmit={handleSubmit}>
    ...
  }
}

What I'm unclear on is why the handler for the form's onSubmit handler is taking in an event for its argument for the Facebook tutorial, but why the starter kit's onSubmit handler is taking the form data... The starter kit is leveraging the redux-form package but I don't see it directly affecting how this handler should be behaving.

回答1:

The key is in redux-form being used as an ES2016 decorator on the SurveyForm class.

...
@reduxForm({
  form: 'survey',
  fields: ['name', 'email', 'occupation', 'currentlyEmployed', 'sex'],
  validate: surveyValidation,
  asyncValidate,
  asyncBlurFields: ['email']
})
export default
class SurveyForm extends Component {
...

The decorator will act as a wrapping function for the SurveyForm, returning a wrapping component.

As you may even have noticed, the SurveyForm component accepts an handleSubmit prop which is not being passed down in the container. This is because it is provided by the @reduxForm decorator. The event is then handled and only the formData is returned to the container handler, the top-level onSubmit prop.

Essentially, you can think about it as reduxForm returning a wrapped SurveyForm component.

You can dive into the code there, but be warned, it's pretty dense.