一生中,我无法让Redux-Form填充初始值。我觉得我已经查看了每个SO问题/答案,但是到目前为止,还没有任何帮助。
以下是我的代码中的一些相关部分:
class Profile extends React.Component {
render() {
return (
<form>
<div>
<Field type="text" name="firstName" label="First Name" component={rfField} />
</div>
</form>
);
}
}
const mapStateToProps = (state) => {
return {
initialValues: {
firstName: state.getIn(['user', 'firstName'])
}
};
};
const profileForm = reduxForm({
form: 'profile',
enableReinitialize: true
})(Profile);
const withConnect = connect(mapStateToProps);
const withReducer = injectReducer({ key: 'profile', reducer });
const withSaga = injectSaga({ key: 'profile', saga });
export default compose(withReducer, withSaga, withConnect)(profileForm);
状态具有我在mapStateToProps
中从中获取的值,但是该字段未显示初始值;它仍然是空的。如果我将state.getIn(...)
更改为原义的'test',则该字段保持为空。如果我将initialValues
移至reduxForm(...)
调用,仅使用'test'而不是state.getIn(...)
,则firstName
字段将正确显示'test'。
我认为它与我使用reduxForm
,connect
和compose
函数的方式有关。这是设置react-redux-boilerplate项目的方式,因此我仅使用该范例。
我绝对不是React / Redux专家,所以如果需要任何其他信息,请告诉我。谢谢!
来自package.json:
react: 16.4.0
redux: 4.0.0
react-redux: 5.0.7
redux-form: 7.4.2
答案 0 :(得分:1)
再次更新!
由于似乎mapStateToProps
是异步设置的,因此您需要在state
方法中将React this.props.initialize()
与componentDidUpdate
结合使用。
this.props.formFields
(或在Redux
状态下使用的任何名称)都需要遵循Field
的{{1}}中指定的相同命名约定。例如:name
应该与{ firstName: "", lastName: "" }
<Field name="firstName" ... />
相匹配。
如果您打算允许用户编辑输入,则还需要<Field name="lastName" .../>
,否则,尽管输入显示了内容,它将提交初始化值。
工作示例:https://codesandbox.io/s/zm3mqw2m4
下面的示例在类的keepDirtyOnReinitialize: true
方法中触发Redux动作(this.props.asyncFormFields
),显示微调器,然后检查类componentDidMount
中的this.props.formFields
是否已更改方法。如果更改了componentDidUpdate
,它将this.props.formFields
设置为this.state.isLoading
,然后提示要使用false
数据初始化Redux Form字段。
SimpleForm.js
this.props.formFields
初始化Redux表单的另一种方法是使用ReduxForm的import React, { Component } from "react";
import { reduxForm } from "redux-form";
import { connect } from "react-redux";
import { asyncFormFields } from "../actions";
import ShowError from "../components/ShowError";
import ShowForm from "../components/ShowForm";
import Spinner from "../components/Spinner";
class SimpleForm extends Component {
state = {
err: "",
isLoading: true
};
componentDidUpdate = (prevProps, prevState) => {
if (this.props.formFields !== prevProps.formFields) {
this.setState({ isLoading: false }, () =>
this.props.initialize({ ...this.props.formFields })
);
}
};
componentDidMount = () => this.props.asyncFormFields();
reinitializeForm = () =>
this.setState({ isLoading: true }, () => this.props.asyncFormFields());
render = () =>
this.props.err ? (
<ShowError err={this.props.err} />
) : this.state.isLoading ? (
<Spinner />
) : (
<ShowForm {...this.props} reinitializeForm={this.reinitializeForm} />
);
}
export default reduxForm({
form: "SimpleForm",
enableReinitialize: true,
keepDirtyOnReinitialize: true
})(
connect(
state => ({ err: state.server, formFields: state.fields }),
{ asyncFormFields }
)(SimpleForm)
);
插件。这有点复杂,涉及更多步骤,但是结果是相同的:
工作示例:https://codesandbox.io/s/xppnmklm7q
SimpleForm.js
formReducer
actions / index.js
import React, { Component } from "react";
import { reduxForm } from "redux-form";
import { connect } from "react-redux";
import { asyncFormFields, initForm } from "../actions";
import ShowError from "../components/ShowError";
import ShowForm from "../components/ShowForm";
import Spinner from "../components/Spinner";
class SimpleForm extends Component {
state = {
err: "",
isLoading: true
};
componentDidUpdate = (prevProps, prevState) => {
if (this.props.formFields !== prevProps.formFields) {
this.setState({ isLoading: false }, () => this.props.initForm(this.props.formFields));
}
};
componentDidMount = () => this.props.asyncFormFields();
reinitializeForm = () => this.setState({ isLoading: true }, () => this.props.asyncFormFields());
render = () =>
this.props.err
? <ShowError err={this.props.err} />
: this.state.isLoading
? <Spinner />
: <ShowForm {...this.props} reinitializeForm={this.reinitializeForm} />
);
}
export default reduxForm({
form: "SimpleForm",
enableReinitialize: true,
keepDirtyOnReinitialize: true
})(
connect(
state => ({ err: state.server, formFields: state.fields }),
{ asyncFormFields, initForm }
)(SimpleForm)
);
reducers / index.js
import axios from "axios";
import { INIT_FORM, SET_FORMFIELDS, SERVER_ERROR } from "../types";
export const asyncFormFields = () => dispatch =>
axios
.get("https://randomuser.me/api/?nat=us&results=1")
.then(({ data: { results } }) =>
dispatch({
type: SET_FORMFIELDS,
payload: {
firstName: results[0].name.first,
lastName: results[0].name.last
}
})
)
.catch(err => dispatch({ type: SERVER_ERROR, payload: err }));
export const initForm = fields => ({ type: INIT_FORM, payload: fields });
答案 1 :(得分:0)
本周,我最终使用Redux-form进行了样本处理,并有了一个想法。对于我的表单,我还使用了具有向导功能的redux表单,它没有保留状态(即使使用destroyOnUnmount: false
也是如此)。为了解决这个问题,我删除了向导功能,仅使用一种形式(向导使用多种形式)并隐藏和显示了问题本身。有人告诉我问题出在多种形式不保持状态。代码如下:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { compose, bindActionCreators } from "redux";
import injectReducer from '../../utils/injectReducer';
import injectSaga from '../../utils/injectSaga';
import { SubmissionError } from 'redux-form';
import { Redirect } from "react-router-dom";
import { fetchQuestions } from './actions';
import reducer from './reducer';
import saga from './sagas';
import QuestionForm from './QuestionForm';
import { addAnswer } from './actions';
export class Quiz extends Component {
constructor(props) {
super(props)
this.submitQuiz = this.submitQuiz.bind(this)
// this.previousPage = this.previousPage.bind(this)
this.state = {
page: 1,
sendToSummary: false,
}
}
componentDidMount(){
return new Promise((resolve, reject) => {
this.props.fetchQuestions(resolve, reject);
this.props.addAnswer();
}).catch((error) => {
throw new SubmissionError(error);
})
}
submitQuiz() {
console.log("sub");
this.setState(() => ({
sendToSummary: true
}))
}
render(){
console.log(this.props, "test");
const { page } = this.state;
const { questions } = this.props
return (
<div className="quiz-form">
{questions ?
<QuestionForm
onSubmit={this.submitQuiz}
// previousPage={this.previousPage}
questions={questions}
/>
: 'loading'}
{(this.state.sendToSummary === true) ? <Redirect to='/summary' /> : null}
</div>
);
}
}
function mapSateToProps(state){
console.log(state)
return {
form: state.get('form'),
questions: state.getIn(['questionSet', 'questions'])
}
}
const mapDispatchToProps = dispatch => ({
fetchQuestions: () => dispatch(fetchQuestions()),
addAnswer: () => dispatch(addAnswer()),
})
const withReducer = injectReducer({key: `questionSet`, reducer});
const withSaga = injectSaga({key: `questionSet`, saga});
const withConnect = connect(
state => mapSateToProps, mapDispatchToProps
);
export default compose(
withReducer,
withSaga,
withConnect,
)(Quiz);
这是表格:
import React, { Component } from 'react';
import RadioButton from '../../components/RadioButton';
import { Field, reduxForm, SubmissionError } from 'redux-form';
import { Button, Form } from 'reactstrap';
import ReactHtmlParser from 'react-html-parser';
import { addAnswer } from './actions';
import { connect } from 'react-redux';
import Progress from '../../components/Progress';
class QuestionForm extends Component {
constructor(props) {
super(props);
this.state = {
selectedValues:[],
isChecked: true,
currentQuestion: 0
};
this.nextPage = this.nextPage.bind(this);
this.previousPage = this.previousPage.bind(this);
}
nextPage(){
if(this.state.currentQuestion !== this.props.questions-1){
this.setState({ currentQuestion: this.state.currentQuestion + 1 })
}
}
previousPage(){
if(this.state.currentQuestion !== 0){
this.setState({ currentQuestion: this.state.currentQuestion - 1 })
}
}
render(){
const { handleSubmit, questions } = this.props;
console.log(this.props.questions)
return (
<form onSubmit={handleSubmit} className="quizForm">
{questions.map((question,i) => {
console.log(i, this.state.currentQuestion)
return (
<div key= {`question-${i}`} className={this.state.currentQuestion === i ? '':'d-none'}>
<h1>{ question.category }</h1>
<h2>{ ReactHtmlParser(question.question) }</h2>
<RadioButton name={`question-${i}`} label="true" radioButtonValue={true} />
<RadioButton name={`question-${i}`} label="false" radioButtonValue={false} />
<Button type="button" onClick={this.previousPage} className="next">
Previous
</Button>
{this.state.currentQuestion === questions.length-1 ? <Button type="submit" className="next" onClick={() => this.nextPage(i)}>
Submit
</Button>: <Button type="button" className="next" onClick={() => this.nextPage(i)}>
Next
</Button>}
</div>
)
})}
<Progress page={this.state.currentQuestion + 1} total={10}/>
</form>
)
}
}
function mapStateToProps(state){
console.log(state)
return {
form: state.get('form'),
questions: state.getIn(['questionSet', 'questions'])
}
}
const mapDispatchToProps = dispatch => ({
fetchQuestions: () => dispatch(fetchQuestions()),
addAnswer: () => dispatch(addAnswer()),
})
QuestionForm = connect(state => (mapStateToProps, mapDispatchToProps))(QuestionForm)
export default reduxForm({
form: 'quiz_form',
destroyOnUnmount: false,
// forceUnregisterOnUnmount: true,
// keepDirtyOnReinitialize: true
})(QuestionForm);