redux-form: [v8.1.0] initialValues are undefined at first render

Are you submitting a bug report or a feature request?

Bug Report

What is the current behavior?

When providing inivialValues, on first render the value specified in initialValues is undefined

What is the expected behavior?

In v7.4.2 the value passed as initialValue was available at first render. I couldn’t find any information about it in changelog so i assume this should work as in v7.4.2.

Sandbox Link

i’ve created a simple component - reduxForm() is created using an initialValue, then it is passed to the component using connect() and formValueSelector. Observe the console.logs: redux-form@8.1.0 https://codesandbox.io/s/54pn3nvv8n

firstname undefined
firstname john

redux-form@7.4.2 https://codesandbox.io/s/lrk4y97qw9

firstname john
firstname john

Is it a bug or is it now an expected behaviour?

Other information

here’s the code (same as in codesandbox):

const valueSelector = formValueSelector("myform");
const enhance = compose(
  reduxForm({
    form: "myform",
    initialValues: { firstname: "john" }
  }),
  connect(state => ({
    firstname: valueSelector(state, "firstname")
  }))
);

class Page extends PureComponent {
  render() {
    console.log("firstname", this.props.firstname);
    return (
      <div>
        <Field name="firstname" placeholder="firstname" component="input" />
      </div>
    );
  }
}

export default enhance(Page);

About this issue

  • Original URL
  • State: open
  • Created 5 years ago
  • Reactions: 35
  • Comments: 22

Commits related to this issue

Most upvoted comments

Is this being worked on? I think it is a big fat bug, right?

A quick update for those who don’t follow ecosystem updates closely: A few weeks ago react-redux published v7.0.0-beta.0 which is a massive reworking of v6; mostly fixing performance issues but also reverting how child components see state changes made by mounting parent components back to the v5 behaviour:

…updates dispatched in React lifecycle methods are immediately reflected in later component updates.

A few people have already tried the new react-redux beta release with redux-form v8 and it fixes this issue. Once it goes gold, should just be a case of updating the dependency for this project and lots of the issues we’re seeing with v8 will be fixed. As a heads up, react-redux v7 now uses hooks internally so requires React 16.8.4 or higher

Another symptom of this problem is now initial call of validate() receives empty object, despite initialValues being passed to the form. So it breaks validations on FieldArrays which previously worked

I would suggest to everyone not to migrate to v8 version. With the new context API lots of things got broken. Let them sort things out first.

We had to roll back to v7 in the end, v8 is a hot mess right now - I’d recommend people don’t use it.

@Olliebaba thx, i also think it’s related, but in #4304 there are also lifecycle methods being mentioned, which adds more complexity into this issue. I think it can be related to “Behavior Changes” (second one) mentioned here: https://github.com/reduxjs/react-redux/releases/tag/v6.0.0 and i’m not sure if this can be so easily fixed in redux-form, but maybe a note should be added into Breaking Changes list?

However when validating datas, you still have the validate method called twice with empty data => https://codesandbox.io/s/v6xpm1222y

As @jacekkolasa mentioned this is indeed due to changes in react-redux 6. When the parent form component mounts it dispatches an action to set the initialValues, however the child components (including the Fields) use the state before the dispatch occured, meaning that they don’t see the initialValues. This is intentional in react-redux 6 to prevent what is known as “tearing” where child components get a different version of state than their parents. Most of the time this is great and prevents a whole class of bugs but not in our use case.

There is a great detailed discussion of the problem here https://github.com/reduxjs/react-redux/issues/1126

Interestingly there is a workaround provided in this comment https://github.com/reduxjs/react-redux/issues/1126#issuecomment-447341725 - wrapping the Field component in a new <ReactReduxContext.Provider> should give it access to the most current version of the state.

I don’t have time to work on a fix right now but hopefully this points somebody in the right direction.

I think I may have the same problem, but with different function in FieldArray component

this.props.fields.getAll() // return null at first as well

Hope you can take a look at this as well

Wrote a simple hoc as a workaround for this issue

const withFieldInitialValueFix = Component => {
  const FieldInitialValueFix = props => {
    const {
      input,
      meta: { touched, initial },
    } = props;

    const isValueNotInitialized = initial && !input.value && !touched;

    const fixedInput = isValueNotInitialized
      ? {
          ...input,
          value: initial,
        }
      : input;

    return <Component {...props} input={fixedInput} />;
  };

  FieldInitialValueFix.propTypes = {
    input: PropTypes.shape({
      value: PropTypes.any,
    }).isRequired,
    meta: PropTypes.shape({
      touched: PropTypes.bool.isRequired,
      initial: PropTypes.any,
    }).isRequired,
  };

  return FieldInitialValueFix;
};

Just wrap your field’s component to fix for specific cases, or similar logic can be used to override default Field’s behavior. *mb not be suitable for some edge cases, ex. programmatically remove the value at some point.

I think this is definatly should be hadnled as a bug at least because Field’s meta.dirty equalstrue on initial render.

Would love to see this one get some attention. This is definitely the biggest issue affecting V8 adoption for us. @erikras , any ideas?

A lot of code is broken at new version and lot of code depends on it right now, and cannot switch to previous redux-form version due withRef react changes. Need time to move old code to final form