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

current values? #2253

Closed
arolson101 opened this Issue Dec 9, 2016 · 13 comments

Comments

Projects
None yet
10 participants
@arolson101
Copy link

arolson101 commented Dec 9, 2016

Previous versions of redux-form injected a 'values' property that you could use to inspect the form's current values. Is there any way to get that in the new version?

@jole78

This comment has been minimized.

Copy link

jole78 commented Dec 12, 2016

could you use formValueSelector in combo with connect...??

@mokone91

This comment has been minimized.

Copy link

mokone91 commented Dec 12, 2016

Hi, I use formValueSelector, but in this case i should pass extra property with this value to form.

I think its will be nice, if we will can get value of form inside the form and skip extra property

Thanks!
Eldar.

@Aaronius

This comment has been minimized.

Copy link
Contributor

Aaronius commented Dec 13, 2016

@mokone91 I think v6 of redux-form intentially doesn't provide you the values without using formValueSelector due to performance reasons. Always providing the current value of the fields is expensive with large forms. The performance benefit of not doing that is one of the "features" of v6, though inconvenient at times.

@jole78

This comment has been minimized.

Copy link

jole78 commented Dec 13, 2016

@arolson101 could you perhaps give a use case for wanting all the values in your form and we can advise on an alternative perhaps?

@esseswann

This comment has been minimized.

Copy link

esseswann commented Dec 13, 2016

@jole78 simplest example - your select field options depend on another field value

@jole78

This comment has been minimized.

Copy link

jole78 commented Dec 13, 2016

@esseswann so basically you need to use the formValueSelector to "listen" to state changes on the dependent field and use that value as input into another field for selection?
something like this....?? (or tell me more what you need)

const mapStateToProps = (state, ownProps) => {
  const selector = formValueSelector('THE_FORM')
  return {
    somefield: selector(state, 'some_field')
  }
}
...// and in the form
<Field
  name="some_other_field"
  component={SomeOtherComponent}
  somefield={this.props.some_field} />

const SomeOtherComponent = (props) {
   if(props.somefield) {
    // ....do whatever
  }
}
@arolson101

This comment has been minimized.

Copy link
Author

arolson101 commented Dec 13, 2016

My use case is to conditionally change form values based on an event. Specifically, choosing a select value will auto-fill some form fields unless the user has changed them.

The values don't need to be properties, specifically; just having a function I could call to get the values would be sufficient.

@mokone91

This comment has been minimized.

Copy link

mokone91 commented Dec 13, 2016

@jole78 i my case, i trying to write reusable form, so the idea is - make so independent form as it possible,
so if i can get access to value inside form, then i cant forgot about this dependency at all.

for example: color picker which can change self color dependent on selected value. to use it across the app i should pass the selected property from each parent component.

Thanks!

@cdaringe

This comment has been minimized.

Copy link

cdaringe commented Dec 16, 2016

@arolson101, i have the same need. i'm sure we can find a better way to do this in the future, however, i did write https://www.npmjs.com/package/reduxify-form for this same issue.

@gustavohenke

This comment has been minimized.

Copy link
Collaborator

gustavohenke commented Mar 2, 2017

Most of these use cases may be resolved by using the Fields component.
Take a look, try some stuff, and if you still have questions, please ask it over StackOverflow.

@afraser

This comment has been minimized.

Copy link

afraser commented Jan 9, 2018

I have a form that has a button that's supposed to show the whole form in a json structure. The current implementation makes this pretty awkward.

I managed to get the values by connecting to the form store directly:

eg:

let MyForm = props =>
   props.formState // <== undefined on first render?
     ? <form>...</form>
     : null

MyForm = reduxForm({
  form: 'myForm'
})(MyForm);

const mapStateToProps = (state, ownProps) => ({
  formState: state.form.myForm,  // <== Inject the form store itself
});

export default connect(mapStateToProps)(MyForm);
@tnrich

This comment has been minimized.

Copy link

tnrich commented Apr 10, 2018

@gustavohenke calling handleSubmit() will spit out a data object with the form values in it. Why not expose a getValues() function and allow it to be called to retrieve the current values regardless of whether they're all valid or not.

Then we could do great things like:

onSendPartialValuesClicked = () => {
	myApi.sendPartialVals(this.props.getValues())
}

This is a contrived example but the point still stands that now we can access the form values but don't have to listen to all the form values and re-render every time. Seems like it would be so simple..

@erikras

@xurei

This comment has been minimized.

Copy link

xurei commented Aug 1, 2018

I came across this problem several times, and using Fields feels overcomplicated to me.
So I made this helper component to deal with that.
I'm really interested in your reviews, guys. It would be wonderful to have that in the official API.
@erikras What's your opinion ?

import React from 'react'; //eslint-disable-line no-unused-vars
import PropTypes from 'prop-types';
import deepEqual from 'deep-eql';
import { connect } from 'react-redux';
import { formValueSelector } from 'redux-form';

/**
 * Used in conjunction with redux-form. Allow to watch some current values in a form, to ease conditional rendering
 */
class CurrentValues extends React.Component {
    static propTypes = {
        names: PropTypes.array.isRequired,
    };
    static contextTypes = {
        _reduxForm: PropTypes.object
    };
    
    constructor(props, context) {
        super(props, context);
        const formName = this.context._reduxForm.form;
        this.component = createCurrentValues(formName, props.names);
    }
    
    render() {
        const props = this.props;
        const childProps = Object.assign({}, props, {names:undefined});
        const Component = this.component;
        
        return (
            <Component {...childProps}/>
        );
    }
    
    shouldComponentUpdate(nextProps) {
        const props = this.props;
        if (!deepEqual(props.names, nextProps.names)) {
            const formName = this.context._reduxForm.form;
            this.component = createCurrentValues(formName, props.names);
        }
        return true;
    }
}

function createCurrentValues(formName, names) {
    class CurrentValuesSub extends React.Component {
        static propTypes = {
            values: PropTypes.object.isRequired,
        };
        static displayName = `CurrentValues(${formName})`;
        
        render() {
            const props = this.props;
            return (
            <div className={props.className}>
                {this.props.children(props)}
            </div>
            );
        }
        
        shouldComponentUpdate(nextProps) {
            return !deepEqual(this.props, nextProps);
        }
    }
    
    const selector = formValueSelector(formName);
    return connect(
        state => {
            const valueObj = {};
            names.forEach(key => {
                valueObj[key] = selector(state, key);
            });
            return { values: valueObj };
        }
    )(CurrentValuesSub);
}

export { CurrentValues };

Usage:

{/* business as usual */}
<Field name="myfield" component="input"/>

{/* watch myfield */}
<CurrentValues names={['myfield']} {...props}>
    {props => (
        <div>
            {/* should contain {values: {myfield: '...'}} */}
            <pre>{JSON.stringify(props, null, '  ')}</pre>
        </div>
    )}
</CurrentValues>

[EDIT] Using redux connect instead of direct access to context when possible

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment