初始化 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)
所以我有一个简单的形式 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)