53 votes

Valeurs initiales Redux-Form de

Je suis en train de remplir le formulaire de profil avec les données de l'API. Malheureusement redux-forme ne veulent pas coopérer avec moi dans cette affaire. Pour une raison quelconque champs reste vide, quoi que je fasse.

Réglage de la correction des valeurs à la place des valeurs passées de réducteur de bien fonctionner pour une raison quelconque.

C'est peut-être parce que je suis en utilisant redux-promesse pour les appels de l'API à l'intérieur de l'action de créateurs? Comment puis-je vivre avec elle et de se débarrasser de cette. Voici mon formulaire de composant.

import React, { Component } from 'react';
import { reduxForm, Field } from 'redux-form';
import { connect } from 'react-redux';
import { fetchRoleList, fetchUserData } from '../actions';

class UserEdit extends Component {

    componentWillMount() {
        this.props.fetchRoleList();
        this.props.fetchUserData();
    }

    handleEditProfileFormSubmit(formProps) {
        console.log(formProps);
    }

    getRoleOptions(selected_id) {
        if (!this.props.profile) {
            return <option>No data</option>;
        }

        return this.props.profile.roles.map(role => {
            return <option key={role.role_id} value={role.role_id}>{role.name}</option>;
        });
    }

    renderField(props) {
        const { input, placeholder, label, value, type, meta: { touched, error } } = props;
        return (
        <fieldset className={`form-group ${ (touched && error) ? 'has-error' : '' }`}>
            <label>{label}</label>
            <input className="form-control" {...input} type={type} placeholder={placeholder} />
            {touched && error && <div className="error">{error}</div>}
        </fieldset>
        );
    }

    renderSelect({ input, placeholder, options, label, type, meta: { touched, error } }) {
        return (
        <fieldset className={`form-group ${ (touched && error) ? 'has-error' : '' }`}>
            <label>{label}</label>
            <select className="form-control" {...input}>
                {options}
            </select>
            {touched && error && <div className="error">{error}</div>}
        </fieldset>
        );
    }

    render() {
        const { handleSubmit } = this.props;

        const user = this.props.profile.user;

        return (
        <div> {user ? user.email : ''}
            <form onSubmit={handleSubmit(this.handleEditProfileFormSubmit.bind(this))}>
                <Field name="email" label="Email:" component={this.renderField} type="text" placeholder="email@gmail.com" className="form-control"/>
                <Field name="name" label="Name:"  component={this.renderField} type="text" placeholder="John Doe" className="form-control"/>
                <Field name="role" label="Role:" component={this.renderSelect} type="select" className="form-control" options={this.getRoleOptions()}/>
                <button action="submit" className="btn btn-primary">Edit user</button>

                <Field name="password" label="Password:" component={this.renderField} type="password" className="form-control"/>
                <Field name="passwordConfirm" label="Confirm Password:" component={this.renderField} type="password" className="form-control"/>
                { this.props.errorMessage
                &&  <div className="alert alert-danger">
                        <strong>Oops!</strong> {this.props.errorMessage}
                    </div> }
                <button action="submit" className="btn btn-primary">Sign up!</button>
            </form>
        </div>
        );
    }

}

let InitializeFromStateForm = reduxForm({
    form: 'initializeFromState'
})(UserEdit);

InitializeFromStateForm = connect(
  state => ({
    profile: state.profile,
    initialValues: state.profile.user
  }),
  { fetchRoleList, fetchUserData }
)(InitializeFromStateForm);

export default InitializeFromStateForm;

Je ne crois action créateur sera utile:

export function fetchUserData(user_id) {
    user_id = user_id ? user_id : '';

    const authorization = localStorage.getItem('token');
    const request = axios.get(`${ROOT_URL}/user/${user_id}`, {
      headers: { authorization }
    });

    return {
        type: FETCH_USER,
        payload: request
    };
}

108voto

FurkanO Points 2703

Vous devez ajouter enableReinitialize: true comme ci-dessous.

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

Si votre prop initialValues est mis à jour, votre formulaire sera également mis à jour.

7voto

Arian Acosta Points 1796

Pour définir l' initialValues il est important d'appliquer l' reduxForm() décorateur avant de l' connect() décorateur de redux. Les champs ne seront pas remplir à partir du magasin de l'état, si l'ordre des décorateurs est inversé.

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

Si, en plus de définir les valeurs pour la première fois, vous avez besoin de re-remplir le formulaire à chaque fois que les modifications d'état puis définissez enableReinitialize: true

Trouver un exemple simple dans cette réponse.

Lire l'officiel de la documentation et de l'exemple complet.

Lisez à propos de cette question ici.

2voto

please delete me Points 206

Donc, vous êtes à essayer:

  • Chargement de l'API de données dans le formulaire
  • Mettre à jour le formulaire juste en charge (aka. initialValues)

Tandis que @FurkanO pourrait fonctionner, je pense que la meilleure approche est de charger le formulaire lorsque vous avez obtenu toutes asynchrone de données, vous pouvez le faire en créant un composant parent / conteneur:

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} />}
 );
} 

Fondamentalement, ce que vous devriez faire dans l' UserEditLoader , est d'exécuter les fonctions de l'API et de la mise à jour de l'état (ou les accessoires si redux connecté). Chaque fois que le profil de la variable n'est pas vide (ce qui signifie que vous avez obtenu les données que vous attendiez) puis montez UserEdit avec le profil de prop.

1voto

initialize () est un accessoire fourni par reduxForm, qui peut être utilisé pour remplir les valeurs du formulaire.

change () est un autre accessoire fourni par reduxFrom pour modifier une valeur de champ.

 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))));
 

0voto

nbeuchat Points 1708

Si l'astuce enableReinitialize : true ne fonctionne pas, vous pouvez mettre à jour chaque champ lorsque le initialValues prop change.

 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]);
            }
        }
    }
}
 

Je n'ai jamais travaillé avec FieldsArray mais je suppose que cela ne fonctionnerait pas ici.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X