wake-up-neo.com

Redux-Form Anfangswerte von

Ich versuche, das Profilformular mit Daten aus der API zu füllen. Redux-form möchte in diesem Fall leider nicht mit mir zusammenarbeiten. Aus irgendeinem Grund bleiben Felder leer, was auch immer ich mache. 

Das Festlegen der festen Werte anstelle der Werte, die vom Reduzierer abgegeben werden, funktioniert aus irgendeinem Grund gut. 

Vielleicht liegt das daran, dass ich redux-promise für API-Aufrufe innerhalb der Aktionsersteller verwende? Wie kann ich damit leben und das loswerden? Hier ist meine Formkomponente.

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 protected]" 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;

Ich glaube, Action Creator wird auch nützlich sein:

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
    };
}
31
J33nn

Sie müssen enableReinitialize: true wie folgt hinzufügen. 

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

Wenn Ihre erste Wert-Requisite aktualisiert wird, wird auch Ihr Formular aktualisiert.

78
FurkanO

Um die initialValues einzustellen, ist es wichtig, den reduxForm() decorator vor dem connect() decorator von redux anzuwenden. Die Felder werden nicht aus dem Speicherstatus ausgefüllt, wenn die Reihenfolge der Dekorateure umgekehrt ist.

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

Wenn Sie nicht nur die Werte zum ersten Mal festlegen, sondern auch jedes Mal, wenn sich der Status ändert, das Formular neu ausfüllen, legen Sie enableReinitialize: true fest.

Ein einfaches Beispiel finden Sie in dieser Antwort .

Lesen Sie die offizielle Dokumentation und das vollständige Beispiel .

Lesen Sie zu diesem Thema hier .

4
Arian Acosta

Du versuchst also:

  • Laden Sie API-Daten in das Formular
  • Aktualisieren Sie das Formular gerade beim Laden (aka. initialValues)

Während @FurkanO möglicherweise funktioniert, denke ich, der beste Ansatz besteht darin, das Formular zu laden, wenn Sie alle asynchronen Daten erhalten haben. Sie können dies jedoch tun, indem Sie eine übergeordnete Komponente/einen übergeordneten Container erstellen:

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

Grundsätzlich sollten Sie in der UserEditLoader die API-Funktionen ausführen und den Status aktualisieren (oder Requisiten, wenn Redux angeschlossen ist). Wenn die Profilvariable nicht leer ist (was bedeutet, dass Sie die erwarteten Daten erhalten haben), hängen Sie UserEdit mit dem Profil als Requisite ein.

2
zurfyx

Wenn der enableReinitialize : true-Trick nicht funktioniert, können Sie jedes Feld aktualisieren, wenn sich die initialValues-Eigenschaft ändert.

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

Ich habe noch nie mit FieldsArray gearbeitet, aber ich gehe davon aus, dass dies hier nicht funktionieren würde. 

1
nbeuchat

initialize () ist eine von reduxForm bereitgestellte Eigenschaft, die zum Auffüllen der Formularwerte verwendet werden kann.

change () ist eine weitere Eigenschaft von reduxFrom, um einen Feldwert zu ändern.

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
Satyendra Singh