3

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 Answer 1

4

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.

Sign up to request clarification or add additional context in comments.

2 Comments

I believe you are correct, though handleSubmit does appear to be passed down as a prop: render() return ( <SurveyForm onSubmit={this.handleSubmit}/> ) Did you mean something else?
In the code, SurveyForm never calls this.props.onSubmit but calls this.props.handleSubmit. Your handler is being bind on the onSubmit prop, meaning it never gets called by SurveyForm directly. In the reduxForm code, you can see it calling this.props.onSubmit. This is tricky because the names are quite similar, but in essence SurveyForm calls this.props.handleSubmit (provided by reduxForm), which in returns calls this.props.onSubmit (your handler).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.