Search code examples
redux-form

When is pristine actually calculated? It seems to always be true, even when the form changes


On redux-form 6.4.2 I have the following form code:

const renderUsers = ({ fields }) => {
  const table = (
    <table className={styleTable.tbody}>
      <thead className={styleTable.thead}>
        <tr>
          <th>Username</th>
          <th>Roles ('acct purch rec')</th>
        </tr>
      </thead>
      <tbody className={styleTable.tbody}>
        {fields.map((userFieldName /* , index */) => (
          <tr key={userFieldName}>
            <td>
              <Field name={`${userFieldName}.username`} component="input" disabled />
            </td>
            <td>
              <Field name={`${userFieldName}.roles`} component="input" />
            </td>
          </tr>
        ))}
      </tbody>
    </table>
  );

  return table;
};

class Form extends Component {
  // Ignore state changes with each user update.
  shouldComponentUpdate(nextProps) {
    return JSON.stringify(this.props.initialValues) !==
           JSON.stringify(nextProps.initialValues);
  }

  render() {
    const { loadUsers, handleSubmit, pristine, reset, submitting, invalid } = this.props;
console.log(pristine, invalid, submitting);
    return (
      <form onSubmit={handleSubmit}>

        <Field name="filter"
          component={TextField}
          props={{ floatingLabelText: 'Starting username', autoFocus: true }}
        />
        <RaisedButton label="Filter"
          disabled={submitting}
          className={style.button}
          onClick={() => loadUsers()}
          secondary
        />
        <br />
        <br />

        <FieldArray name="users" component={renderUsers} />
        <br />

        <div>
          <RaisedButton label={submitting ? 'Changing...' : 'Change'}
            disabled={pristine || invalid || submitting}
            className={style.button}
            type="submit"
            primary
          />
          <RaisedButton label="Clear Values"
            disabled={pristine || submitting}
            className={style.button}
            onTouchTap={reset}
            secondary
          />
        </div>

      </form>
    );
  }
}

Form.propTypes = {
  initialValues: PropTypes.object.isRequired,
  loadUsers: PropTypes.func.isRequired,
  onSubmit: PropTypes.func.isRequired,
  handleSubmit: PropTypes.func.isRequired,
  pristine: PropTypes.bool.isRequired,
  invalid: PropTypes.bool.isRequired,
  reset: PropTypes.func.isRequired,
  submitting: PropTypes.bool.isRequired,
};

I'm experiencing two problems:

  1. the console.log statement outputs true false false every time it outputs anything. I would expect this only on the first output when the page first loads.
  2. the console.log statement only outputs something at these points:

    1. page load
    2. focus on a user role field
    3. type in the filter field
    4. press the filter button

    but it does not output anything at these points:

    1. type in a user role field
    2. blur a user role field

I can see from the Redux DevTools that the state is getting updated properly. For example, the first time I press a key in a user role field, the redux state diff looks like:

redux state diff -- Sorry for the picture, no formatting comes out when I copy the text.

In particular, typing in a user role field (or at least on blur afterwards) would have to trigger a render, and then pristine would have to be false, in order for the form to work. Since neither of these things is happening, the form's submit button stays disabled.

I'm only asking these both in the same question in case there's one simple cause creating both of these sub-issues. The main issue is that the submit button is always disabled, these sub-issues are just what I've been able to figure out.


Solution

  • Pristine is calculated as deepEqual(currentValues, initialValues) on every value change.

    Your problem is that you are explicitly ignoring user changes with your shouldComponentUpdate(). Remove that and it'll work.