初始化 redux-form 向导

Initializing redux-form wizard

所以我有一个简单的形式 wizard 取自 redux-form 的例子。我想用从异步 API 调用接收到的数据初始化字段。

现在的情况是,向​​导的每一页中没有 enableReinitialize: true 参数就不会填充字段,因为在启动服务器请求时初始化已经发生了一次。 另一方面,如果我将 enableReinitialize: true 添加到向导页面,那么在从一个页面移动到另一个页面时,任何用户输入都将被丢弃,并且将再次设置 initialValues。

我也曾尝试将 keepDirtyOnReinitialize: true 选项与 enableReinitialize: true 一起添加到每个页面,但无济于事。

当您需要通过必须由用户覆盖的异步获取数据来初始化字段子集时,创建表单向导的正确方法是什么?

WizardForm.jsx:

import React, {Component, PropTypes} from 'react'
import WizardFormFirstPage from './WizardFormFirstPage.jsx'
import WizardFormSecondPage from './WizardFormSecondPage.jsx'
import WizardFormThirdPage from './WizardFormThirdPage.jsx'
import fetchData from "./fetchData.jsx";
import {connect} from "react-redux";

class WizardForm extends Component {

constructor(props) {
    super(props);
    this.nextPage = this.nextPage.bind(this);
    this.previousPage = this.previousPage.bind(this);
    this.state = {
        page: 1
    }
}

componentWillMount() {
    if (!this.props.hasFetched)
        this.props.fetchData();
}

nextPage() {
    this.setState({ page: this.state.page + 1 })
}

previousPage() {
    this.setState({ page: this.state.page - 1 })
}

render() {
    const { onSubmit } = this.props;
    const { page } = this.state;
    return (
        <div>
            {page === 1 && <WizardFormFirstPage onSubmit={this.nextPage}     initialValues={this.props.initialValues}/>}
            {page === 2 &&
            <WizardFormSecondPage previousPage={this.previousPage} initialValues={this.props.initialValues}
                                  onSubmit={this.nextPage}/>}
            {page === 3 &&
            <WizardFormThirdPage previousPage={this.previousPage} initialValues={this.props.initialValues}
                                 onSubmit={onSubmit}/>}
            <label>{this.props.isFetching ? "Fetching data.." : "Fetched data successfully." }</label>
        </div>
    )
}
}

function mapStateToProps(state) {
    return {
        initialValues: state.prefill.data,
        isFetching: state.prefill.fetching,
        hasFetched: state.prefill.fetched
    }
}

WizardForm = connect(
    mapStateToProps,
    {fetchData}
)(WizardForm);

WizardForm.propTypes = {
    onSubmit: PropTypes.func.isRequired,
    initialValues: PropTypes.object
};

export default WizardForm;

WizardFormFirstPage.jsx:

class WizardFormFirstPage extends Component {

    constructor(props) {
        super(props);
    }

    render() {
        const {handleSubmit} = this.props;
        return (
            <form onSubmit={handleSubmit}>
                <Field name="firstName" type="text" component={renderField} label="First Name"/>
                <Field name="lastName" type="text" component={renderField} label="Last Name"/>
                <Field name="downPayment" type="text" component={renderField}
                       label="Down Payment" normalize={normalizeDownPayment}/>
                <div>
                    <button type="submit" className="next">Next</button>
                </div>
            </form>
        )
    };
}

WizardFormFirstPage = reduxForm({
    form: "wizard",
    destroyOnUnmount: false,
    forceUnregisterOnUnmount: true,
    //enableReinitialize: true, // <-- !
    validate
})(WizardFormFirstPage);

export default WizardFormFirstPage;

fetchData.jsx:

export default function fetchData() {
    return (dispatch) => {
        dispatch({type: "FETCH_DATA_START"});
        axios.get("http://rest.learncode.academy/api/nordischby/customer")
            .then(response => {
                dispatch({type: "FETCH_DATA_FINISH", data: response.data[0]});
            })
            .catch(error => {
                console.error(error);
            });
    }
};

prefill.jsx:

const initialState = {
    data: {},
    fetching: false,
    fetched: false,
    error: null
};

const prefillReducer = (state = initialState, action) => {
switch (action.type) {
    case "FETCH_DATA_START":
        return {
            ...state,
            fetching: true
        };
    case "FETCH_DATA_FINISH":
        return {
            ...state,
            data: action.data,
            fetching: false,
            fetched: true
        };
        default:
            return state
    }
};

export default prefillReducer;

我发现问题所在了。供日后参考:

我现在为 reduxForm() 使用以下选项:

export default reduxForm({
    form: "wizard",
    destroyOnUnmount: false,
    //forceUnregisterOnUnmount: true, // <-- This bad boy was wrong
    keepDirtyOnReinitialize: true,
    enableReinitialize: true,
    validate
})(WizardFormThirdPage)