Redux-form: [v7.4.0] initialValues not working

Created on 12 Jun 2018  路  38Comments  路  Source: redux-form/redux-form

Are you submitting a bug report or a feature request?

bug report

What is the current behavior?

initialValues prop is not working on initial mount after update to 7.4.0

Sandbox Link

I've modified the Initialize from state demo just to show the issue. I've just change:

 state => ({
    initialValues: data
 }),

to get values directly from the variable instead after clicking the button.

https://codesandbox.io/s/ox3p66023q

As you can see the fields are empty. If you change the redux-form version to 7.3.0 it works.

What's your environment?

redux-form 7.4.0

bug

Most helpful comment

I believe this is still a bug, my solution is to call this.props.initialize() in componentDidMount();

All 38 comments

just updated from 7.3 to 7.4 and seeing the same thing. all our initial values are gone. seeing no errors. using redux 4.0.0

Same issue here. Using redux v 3.x.x. Had to downgrade to v.7.3to make things work again

I updated to react 16.4 and that seemed to have fixed it. I was using 15.4 before.

I can confirm this issue on react 15.6.2. The redux-form/INITIALIZE event does not fire

Thanks for the confirmation, folks.
If you can look at this issue and find a proper fix, we'll be able to get this released sooner.

also i have a lot of bugs with 7.4.0, in general form init and validators not working at all (react 15.6.2 and redux-form 7.4.0). now i'm looking where is problem

I just spent a couple hours trying to diagnose this as well. Pinning to version 7.3.0 in your package.json will fix the issue.

It appears that, in createReduxForm, componentWillMount is no longer being called, and thus initIfNeeded is not hitting its first pass at initialization because a nextProps argument is always passed by componentDidMount (the next lifecycle method that calls initIfNeeded).

This is because the method name changed to UNSAFE_componentWillMount in order to support React 16's unsafe versions of deprecated lifecycle methods. By doing so, support for React v15 is now broken in v7.4.0.

I would imagine that having two methods, UNSAFE_componentWillMount and componentWillMount, living side by side doing the same work, would guarantee full support for React 15 and 16, but I haven't tried yet. EDIT: Or you could just go back to only using componentWillMount, as that is still going to be supported until React 17 comes out, at which point this package could do a major version breaking change bump to support React 17.

Maintainers, please let me know if you'd like a PR with my proposed solution!

I'm just glad to see the Redux Forms authors have as tough a time testing their library as I do.

Adding to @JoshMock's point, it appears that react-final-form has a dependency on react-lifecycles-compat for this reason. Perhaps this is the simple fix? I'm not sure, but will try to test later this afternoon if someone doesn't get to it before I do.

Hello folks, thanks for looking at this issue with a magnifying glass.
We don't really have workforce to deal with code changes nowadays (most recent changes are from you, dear users), so if any of you could make the PR, that would be great.
I think @jpdesigndev's idea is simple enough to require little review, so I would 馃憤 it 馃檪

@gustavohenke, @jpdesigndev, @JoshMock
Let's be clear:

  • The hotfix should be to revert to the straight cWM, cWRP, and cWU. See #4078.
  • The actual fix is to migrate all uses of these old life cycle methods, when doing so we use react-lifecycles-compat to continue support for React 15. Until then we cannot avoid the deprecation warnings that come with StrictMode in React 16.4.
  • Use of UNSAFE_ methods are only appropriate when the React version is known to be 16+ (i.e. for application authors).

See: open-source-project-maintainers & gradual-migration-path sections of the react blogs update-on-async-rendering

Published fix in v7.4.1.

Not fixed yet.

Thank you guys for the follow up!. You are awesome. I'm afraid i've got some bad news. Just update to v4.7.1 but it's still not working. I've updated the redux-form version in codesandbox and the problem persist.

Published _ACTUAL_ fix in v7.4.2.

It is working now. BIG thanks!

Thank you guys!
I thought I was having this issue but after I upgraded I realized that I'm seeing https://github.com/erikras/redux-form/issues/3879 (reduxForm just passes through the initialValues prop, which I'm not using; calling initialize() doesn't affect the initialValues it passes to the wrapped component 馃槺 ). I was really confused by this... it doesn't seem wise to pass initialValues to the wrapped component unless it is the initial coming from redux state.

@jedwards1211 could you elaborate? I seem to have the same issue with version 7.4.2 and React 16.5.0, but there is a very real possibility I might have overlooked something..

Actually, I finally found an issue someone already filed for what I'm talking about: #3459
(initialize() action creator should update initialValues props)

I believe this is still a bug, my solution is to call this.props.initialize() in componentDidMount();

[redux-form version 8.1.0]
I use this.props.initialize() in componentDidMount(), it's OK.
However, if I use it in componentWillReceiveProps, it not working.

I have tried above solution but still its not working. It's not updating initial value of props.

redux state and everything is fine but rerender is not being called.

I believe this is still a bug, my solution is to call this.props.initialize() in componentDidMount();

One more option:
componentDidMount { this.props.initialize(this.props.myFormData) }

I'm having the same problem with "redux-form": "^8.2.3", and "react": "^16.8.6",.

Calling this.props.initialize() in componentDidMount(); worked for me!

I'm having the same problem with "redux-form": "^8.2.3", and "react": "^16.8.6",.

Calling this.props.initialize() in componentDidMount(); worked for me!

Same here

Bug still can be reproduced under "redux-form": "8.2.2" and "react": "^16.8.6". The issue has to be reopened.

I can confirm this is still an issue ([email protected] & [email protected]).

I have a slightly different work around.
I want to keep my component functional, so don't want to call initialize() in a lifecycle method. The work around I have for setting initial values from state is to call change() in a useEffect hook. In my case I am wanting to set a form value to some state that is not changing:

  /* Workaround to be able to call change in useEffect
     regtype here is a prop mapped to some state in mapStateToProps.
   */      
  const latestChange = useRef(change);
  useEffect(() => {
    latestChange.current = change;
  }, [change]);

  useEffect(() => {
    latestChange.current('RecordType', regtype);
  }, [regtype]);

The first useEffect() is required so that we don't need to add change as a dependency in the second (which would cause the useEffect function to execute continuosly).

I'm sure there are better ways to do this..

@made-in-nz FWIW you don't need that first useEffect, you can just do this

const latestChange = useRef(change);
latestChange.current = change;

And really, you can probably just get away with

  useEffect(() => {
    change('RecordType', regtype);
  }, [regtype]);

because the closure of that function always comes from a single render, so change and regtype will be equally up-to-date.

Thanks @jedwards1211 for the first suggestion, that makes sense.
The second suggestion is what I started with, however I am then getting the warnings:

React Hook useEffect has a missing dependency: 'change'. Either include it or remove the dependency array. If 'change' changes too often, find the parent component that defines it and wrap that definition in useCallback react-hooks/exhaustive-deps

The behaviour is fine though.

Yeah, that's a linting rule designed to make sure you don't accidentally leave out necessary dependencies...it can be nice to intentionally omit something in cases like this, but having the linting rule is also handy 馃し鈥嶁檪
I guess the linting rule only excludes refs from consideration?

This issue can be easily reproduced by providing same initialValues twice.

This issue can be easily reproduced by providing same initialValues twice.

Can confirm, for me this was the reason the form values did not update. Thank you @andrew-aladev for pointing this out 馃檹

Something is completely wrong with the following lines of code.

It is hard to understand this logic. I am reproducing issue with the following env:

const stateInitial ... // undefined
const initialized ... // false
const shouldUpdateInitialValues ... // false
const shouldResetValues ... // false
let initial ... // { ... good data }
initial = stateInitial || empty // { empty object }

So it looks like logic is broken here:

if (!shouldUpdateInitialValues) {
  initial = stateInitial || empty
}

We don't need to update initial values, but why we are resetting it with empty object? See here the following blame.

Everything except if (!shouldUpdateInitialValues) { was updated 3 years ago, but this code is only 1 year ago. So there was some legacy code and people failed to fix it.

This small commit was related to #4020 and it is wrong. We need to fix this issue in another way.

I've updated this code with the following:

const stateInitial = getIn(formState, 'initial')
const stateValues = getIn(formState, 'values')

const initialized = !!stateInitial
const valuesInitialized = !!stateValues

const shouldReinitialize =
  initialized && enableReinitialize &&
  !deepEqual(stateInitial, initialValues)
const shouldUpdateInitial =
  !initialized || shouldReinitialize
const shouldUpdateValues =
  (!valuesInitialized || shouldUpdateInitial) &&
  !keepDirtyOnReinitialize

const initial = shouldUpdateInitial ? initialValues : stateInitial
const values = shouldUpdateValues ? initial : stateValues

const pristine = shouldUpdateValues || deepEqual(initial, values)

Now both initial and values are right, but issue is not fixed, there is bug in another code too.

The following code initIfNeeded is broken too.

When shouldUpdateInitial is true, initIfNeeded don't want to make initialization.

if ((enableReinitialize || !nextProps.initialized) && !deepEqual(this.props.initialValues, nextProps.initialValues)) {

This code is broken.

The line above should be the following:

if (nextProps.initialValues && (!nextProps.initialized || (nextProps.enableReinitialize && !deepEqual(this.props.initialValues, nextProps.initialValues)))) {

I've tested it in our current project and it works perfect.

I will create a pull request later.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

srajchevski picture srajchevski  路  3Comments

tylergoodman picture tylergoodman  路  3Comments

wtfil picture wtfil  路  3Comments

yy-hh picture yy-hh  路  3Comments

2easy picture 2easy  路  3Comments