redux-form icon indicating copy to clipboard operation
redux-form copied to clipboard

[v8.1.0] initialValues are undefined at first render

Open jacekkolasa opened this issue 6 years ago • 22 comments
trafficstars

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: [email protected] https://codesandbox.io/s/54pn3nvv8n

firstname undefined
firstname john

[email protected] 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);

jacekkolasa avatar Jan 02 '19 16:01 jacekkolasa

This appears to be related to #4304.

Olliebaba avatar Jan 02 '19 17:01 Olliebaba

@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?

jacekkolasa avatar Jan 02 '19 20:01 jacekkolasa

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

levino avatar Jan 15 '19 07:01 levino

Running into the same issue here, any word on this?

srisonti avatar Jan 16 '19 03:01 srisonti

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.

AgentCoop avatar Jan 16 '19 06:01 AgentCoop

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.

jamesmoss avatar Jan 24 '19 11:01 jamesmoss

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

vincentjames501 avatar Jan 28 '19 06:01 vincentjames501

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.

denich avatar Jan 28 '19 21:01 denich

I am under the impression that maintenance is not happening here. Is this pipelined to be fixed?

@denich Would it not be easier (and much better) to just write a PR which fixes the issue than patching this manually?

levino avatar Jan 29 '19 06:01 levino

Thanks for the workaround @denich , hope this will be fixed in the library soon!

ingro avatar Feb 01 '19 11:02 ingro

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

KamiGim avatar Feb 05 '19 07:02 KamiGim

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

pokonski avatar Feb 07 '19 05:02 pokonski

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.

jamesmoss avatar Mar 22 '19 11:03 jamesmoss

Same, react-redux 6 is completely broken but they are apparently working on a solution

pokonski avatar Mar 22 '19 11:03 pokonski

We are facing same issue when we use react SSR(server side render). As we know, server side render will only render once on the server side, which resulting in empty input html.

happier2 avatar Apr 04 '19 01:04 happier2

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

jamesmoss avatar Apr 04 '19 09:04 jamesmoss

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

TomPradat avatar Apr 12 '19 14:04 TomPradat

the same issues with validation after updating react, redux, form and correlated packages to latest versions, first two calls come with empty data

AuthorProxy avatar Aug 04 '19 13:08 AuthorProxy

The author has abandoned this project and is now working on final form. Issue should be closed as won't fix

levino avatar Aug 05 '19 04:08 levino

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

AuthorProxy avatar Aug 05 '19 11:08 AuthorProxy

Any news on this, facing the same issues even with redux-form 8.3.6

eugensunic avatar Sep 19 '20 15:09 eugensunic

This might be resolved with 8.3.10. From a first look, I didn't encounter the problem anymore.

darekkay avatar Nov 10 '23 14:11 darekkay