Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

My render and validate functions are only called once #209

Closed
jpierson opened this issue Nov 2, 2015 · 10 comments
Closed

My render and validate functions are only called once #209

jpierson opened this issue Nov 2, 2015 · 10 comments

Comments

@jpierson
Copy link

jpierson commented Nov 2, 2015

I just started attempting to implement my first form using redux-form and synchronization validation and submission don't appear to be working. Setting breakpoints in Chrome I see that validate and render are called for my form component when the component loads for the first time but not beyond that. I've tried typing in the fields which doesn't call validate as I would expect and clicking the submit button results in the following error in the browser console.

Uncaught Error: You must either pass handleSubmit() an onSubmit function or pass onSubmit as a propcheck @ createHigherOrderComponent.js:206handleSubmit @ createHigherOrderComponent.js:213ReactErrorUtils.invokeGuardedCallback @ ReactErrorUtils.js:68executeDispatch @ EventPluginUtils.js:79executeDispatchesInOrder @ EventPluginUtils.js:102executeDispatchesAndRelease @ EventPluginHub.js:43executeDispatchesAndReleaseTopLevel @ EventPluginHub.js:54forEachAccumulated @ forEachAccumulated.js:23EventPluginHub.processEventQueue @ EventPluginHub.js:259runEventQueueInBatch @ ReactEventEmitterMixin.js:18ReactEventEmitterMixin.handleTopLevel @ ReactEventEmitterMixin.js:34handleTopLevelWithoutPath @ ReactEventListener.js:93handleTopLevelImpl @ ReactEventListener.js:73Mixin.perform @ Transaction.js:136ReactDefaultBatchingStrategy.batchedUpdates @ ReactDefaultBatchingStrategy.js:62batchedUpdates @ ReactUpdates.js:94ReactEventListener.dispatchEvent @ ReactEventListener.js:204

I'm following for what most part is very close to the synchronous validation example except for that I wasn't able to get the static propTypes field declaration working so I opted to using the MyComponent.propTypes syntax instead.

@erikras
Copy link
Member

erikras commented Nov 2, 2015

The examples are being rendered with an onSubmit prop passed to them (option B, below). Your problem is exactly what the error says. If you're going to use handleSubmit, you need to either:

A. pass it a function to call.

<button onClick={handleSubmit(data => {
  // do something with data. validation will have been called at this point,
  // so you know the data is valid
})}>Submit</button>

B. pass in such a function as the onSubmit prop to your decorated component.

<MyDecoratedForm onSubmit={data => {
  // do something with data. validation will have been called at this point,
  // so you know the data is valid
}}/>

Does that help?

@jpierson
Copy link
Author

jpierson commented Nov 2, 2015

Ah, Ok. So perhaps this is related to issue #197 in that without an example of the parent it's not always clear what the public interface to the component looks like. I'm finding this is especially true with how props appear to be injected automatically when using redux (ex. fields). Reminds me of some of the same problems I've solved with explicit instantiation issues where I've used Factory abstractions in C# to partially inject parameters within IoC.

I think my intended scenario is B from above. Thank you for taking the time to point out my flaw. I'll try and confirm whether it solves my problem.

@jpierson
Copy link
Author

jpierson commented Nov 2, 2015

I've made the following change on the owner component of the form.

<MyDecoratedForm onSubmit={data => {
  alert("Yay, data is valid");
 }} />

The good thing is that I no longer get the error that I reported originally but my validate method is still not called when editing fields and when clicking on the button in the form I'm not seeing the alert. I have a feeling I'm missing something so I'll poke around looking at other posted issues and examples a bit.

@erikras
Copy link
Member

erikras commented Nov 2, 2015

I'll need to see more code, like how you are calling reduxForm()

@jpierson
Copy link
Author

jpierson commented Nov 2, 2015

Here is an example of how I'm calling reduxForm along with all of the related code which has surely been slimmed down from what I'm working with to just focus on a single input field for email.

import React, { Component, PropTypes } from 'react';
import { reduxForm } from 'redux-form';

export const fields = ['email'];

const validate = values => {
  const errors = {};

  // Email
  if (!values.email) {
    errors.email = 'Required';
  }
  return errors;
};

class MyForm extends Component {

  render() {
    const {
      fields: {email},
      handleSubmit,
      resetForm
      } = this.props;

    return (
      <form id="step2">
        <div>
            <label for="email">Email</label>
            <input id="email" type="text" {...email}/>
            {email.touched && email.error && <div>{email.error}</div>}
          </div>
          <button className="pure-button pure-button-warning pure-u-4-5" onClick={handleSubmit}>
            CREATE ACCOUNT
          </button>
      </form>)
  )
};

MyForm.propTypes = {
    fields: PropTypes.object.isRequired,
    handleSubmit: PropTypes.func.isRequired,
    resetForm: PropTypes.func.isRequired
};

var MyDecoratedForm = reduxForm({
  form: 'myform-step2',
  fields,
  validate
})(MyForm);

export default class MyComponent extends Component {
  render() {
    return (
      <div>
        <MyDecoratedForm onSubmit={data => {
          alert("Yay, data is valid");
        }} />
      </div>
    );
  }
}

@jpierson
Copy link
Author

jpierson commented Nov 2, 2015

I updated the example above after realizing that I left out the button element in my form and upon doing so realized that I didn't have the onClick attribute set as they are in the examples. I am now getting validation to occur when the button is pressed but not yet when changing field values. I am getting closer.

@jpierson
Copy link
Author

jpierson commented Nov 2, 2015

Ok, I think I've solved this or at least validate is being called on each input change which is what my original problem was. The issue was caused by an incorrect reducer setup. See the example below which demonstrates the issue I had.

const myTopLevelComponent = combineReducers({
  reducer1,
  reducer2,
  form: reducer2
})

Notice that the line form: reducer2 was a copy paste issue which should have instead been form: formReducer. Making that change corrected all of the state issues I was having.

Knowing that this issue was caused by my mistake in setting up the global state within the store using formReducer I wonder if there would be a way to help point out this type of problem when redux-form is in use. My thought is that possibly if a a ReduxForm component comes across the store in a state that does not appear to be configured with a form field at the root that a console warning or something along those lines could be emitted to help guide developers toward as solution to the problem. Thoughts?

@jpierson jpierson closed this as completed Nov 2, 2015
@erikras
Copy link
Member

erikras commented Nov 2, 2015

Bingo! You nailed it.

The problem with your suggestion is that the form state is lazily loaded, so an empty state is an acceptable starting position. Perhaps it could do something like React does, like run extra diagnostics when not in production mode. I'll consider it.

@jpierson
Copy link
Author

jpierson commented Nov 2, 2015

Perhaps it could do something like React does, like run extra diagnostics when not in production mode. I'll consider it.

I was thinking along those lines too. I'm not familiar with the inner workings of redux-form yet but I was wondering if there may be a spot when the state is used first in a lazy way if there were a way to detect the lack of the reducer configuration as well. Maybe the logging would be deferred a bit but would still happen whenever that lazy evaluation happens. Well if I ever have a reason to dig into the code I guess I'll have a more informed perspective at that time.

Thanks again, the form stuff is working great now as intended.

@lock
Copy link

lock bot commented Jun 3, 2018

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked as resolved and limited conversation to collaborators Jun 3, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants