Redux-Form initial values from

前端 未结 6 1060
名媛妹妹
名媛妹妹 2020-12-08 09:16

I\'m trying to fill the profile form with data from API. Unfortunately redux-form doesn\'t want to cooperate with me in this case. For some reason fields stays empty whateve

相关标签:
6条回答
  • 2020-12-08 09:45

    For a stateless functional component, you can do it like this:

    componentWillMount() {
      this.props.initialize({ discountCodes: ["ABC200", "XYZ500"] });
    }
    

    For a class, you can do it like this:

    const mapStateToProps = state => (
      {
        initialValues: {
          discountCodes: ["ABC200", "XYZ500"]
      }
    );
    
    0 讨论(0)
  • 2020-12-08 09:49

    So, you're trying:

    • Load API data into the form
    • Update the form just on load (aka. initialValues)

    Whilst @FurkanO might work, I think the best approach is to load the form when you got all async data, you can do that by creating a parent component / container:

    UserEditLoader.jsx

    componentDidMount() {
      // I think this one fits best for your case, otherwise just switch it to
      // componentDidUpdate
      apiCalls();
    }
    /* api methods here */
    render() {
     const { profile } = this.props;
     return (
       {profile && <UserEdit profile={profile} />}
     );
    } 
    

    Basically what you should be doing in the UserEditLoader is to execute the API functions and update the state (or props if redux connected). Whenever the profile variable isn't empty (meaning you got the data you were expecting) then mount UserEdit with profile as prop.

    0 讨论(0)
  • 2020-12-08 09:50

    If the enableReinitialize : true trick does not work, you can update each field when the initialValues prop changes.

    componentWillReceiveProps(nextProps) {
        const { change, initialValues } = this.props
        const values = nextProps.initialValues;
    
        if(initialValues !== values){
            for (var key in values) {
                if (values.hasOwnProperty(key)) {
                    change(key,values[key]);
                }
            }
        }
    }
    

    I have never worked with FieldsArray but I assume this would not work here.

    0 讨论(0)
  • 2020-12-08 10:04

    You need to add enableReinitialize: true as below.

    let InitializeFromStateForm = reduxForm({
        form: 'initializeFromState',
        enableReinitialize : true // this is needed!!
    })(UserEdit)
    

    If your initialValues prop gets updated, your form will update too.

    0 讨论(0)
  • 2020-12-08 10:04

    initialize() is a prop provided by reduxForm, that can be used to fill up the form values.

    change() is another prop provided by reduxFrom to change a field value.

    import * as React from 'react';
    import { Field, reduxForm } from 'redux-form';
    import { connect } from 'react-redux';
    import { withRouter } from 'react-router-dom';
    
    const submit = values => {
        // print the form values to the console
        console.log(values)
    }
    
    interface Props {
        history?: any;
        location?: any;
        session?: any;
        handleSubmit?: Function;
        initialize?: Function;
        change?: Function;
    }
    
    class ContactForm extends React.Component<Props, any> {
    constructor(props, state) {
        super(props, state);
        this.state = {
            value: ''
        };
    }
    
    componentDidMount() {
        const { initialize, session, location } = this.props;
    
        console.log(location.pathname);
    
        if (session && session.user) {
            const values = {
                firstName: session.user.name,
                lastName: session.user.lastName,
                email: session.user.email
            };
            initialize(values);
        }
    }
    
    componentWillReceiveProps(nextProps) {
        const { initialize, session } = this.props;
    
        if (nextProps.session !== session) {
            if (nextProps.session && nextProps.session.user) {
                const values = {
                    firstName: nextProps.session.user.name,
                    lastName: nextProps.session.user.lastName,
                    email: nextProps.session.user.email
                };
                initialize(values);
            } else {
                const values = {
                    firstName: null,
                    lastName: null,
                    email: null
                };
                initialize(values);
            }
        }
    }
    
    render() {
        const { handleSubmit, change } = this.props;
        return (
            <React.Fragment>
                <form onSubmit={handleSubmit(submit)}>
                    <div>
                        <label htmlFor="firstName">First Name</label>
                        <Field name="firstName" component="input" type="text" />
                    </div>
                    <div>
                        <label htmlFor="lastName">Last Name</label>
                        <Field name="lastName" component="input" type="text" />
                    </div>
                    <div>
                        <label htmlFor="email">Email</label>
                        <Field name="email" component="input" type="email" />
                    </div>
                    <button type="submit">Submit</button>
                </form>
    
    
    
                <input type="text" value={this.state.value}
                    onChange={(e) => {
                        this.setState({ value: e.target.value });
                        change('firstName', e.target.value);
                    }}
                />
            </React.Fragment>
        );
    }
    }
    
    export default connect((state) => {
        return {
            session: state.session
        }
    },
    {}
    )(withRouter((reduxForm({
        form: 'contact'
    })(ContactForm))));
    
    0 讨论(0)
  • 2020-12-08 10:09

    To set the initialValues it is important to apply the reduxForm() decorator before the connect() decorator from redux. The fields will not populate from the store state if the order of the decorators is inverted.

    const FormDecoratedComponent = reduxForm(...)(Component)
    const ConnectedAndFormDecoratedComponent = connect(...)(FormDecoratedComponent)
    

    If, in addition to setting the values for the first time, you need to re-populate the form every time the state changes then set enableReinitialize: true

    Find a simple example in this answer.

    Read the official documentation and full example.

    Read about this issue here.

    0 讨论(0)
提交回复
热议问题