#javascript #react-redux #redux-form
#javascript #реагировать-redux #переопределение формы
Вопрос:
Я использую библиотеку для определения города и штата на основе почтового индекса, введенного на экране-заставке. У меня есть значения, переданные на требуемую страницу, но я не могу поместить значение во входные данные формы.
Ранее я работал с этим, используя
componentDidMount() {
this.props.initialize({city: this.city, state:this.state, zipCode:this.zipCode });
}
но это очистило бы значения в остальной части формы. Я попытался установить destroyOnUnmount в false и forceUnregisterOnUnmount в true и все равно очистил бы значения. Я не уверен, куда двигаться дальше с этим без реструктуризации формы redux. Мой код:
CarObjectInfo.js
import vinDecoder from 'vin-decode';
export const getCarYear = (vinNumber) =>{
var carYear;
var carObject = vinDecoder(vinNumber).decode();
return carYear = carObject['year'];
};
Address.js
import React, { Fragment, Component} from 'react';
import { Field, reduxForm, formValueSelector } from 'redux-form';
import RenderField from './fields/RenderField';
import zipField from './fields/zipField';
import { ZipCodeValidator, validZipCode} from '../../helpers/form_validators/ZipCodeValidator';
import {GeneralFieldValidators, requiredStreetAddress, validStreetAddress, requiredCity, validCity} from '../../helpers/form_validators/GeneralFieldValidators'
import { Progress } from 'reactstrap';
import {connect} from 'react-redux';
const renderError = ({ meta: { touched, error } }) =>
touched amp;amp; error ? <span>{error}</span> : false;
const state = ['AL', 'AK', 'AZ', 'AR', 'CA', 'CO', 'CT', 'DE',
'FL', 'GA', 'HI', 'ID', 'IL', 'IN', 'IA', 'KS', 'KY', 'LA', 'ME',
'MD', 'MA', 'MI', 'MS', 'MO', 'MT',
'NE', 'NV', 'NH', 'NJ', 'NM', 'NY', 'NC', 'ND', 'OH', 'OK', 'OR',
'PA', 'RI', 'SC', 'SD', 'TN', 'TX', 'UT', 'VT', 'VA', 'WA', 'WV',
'WI', 'WY'];
const renderStateSelector = ({ input, label, type, meta: {
touched, error } }) => (
<Fragment>
<label htmlFor={label}>{label}</label>
<div>
<select {...input} type={type} className="form-control">
<option value=""></option>
{state.map(val => <option value={val} key={val}>{val} .
</option>)}
</select>
{touched amp;amp; error amp;amp; <span className="errorMessage">{error} .
</span>}
</div>
</Fragment>
);
const requiredState = value => value ? undefined : 'Please provide a
state'
class Address extends Component{
constructor(props){
super(props)
this.handleSubmit = this.props.handleSubmit;
this.previousPage = this.props.previousPage;
this.zipCode = this.props.zipCode;
this.city = getCity(this.zipCode);
}
render (){
const {handleSubmit, previousPage, firstName, zipCode, city} =
this.props;
return (
<Fragment>
<Logo />
{/*Fragment is equivalent to wrapping it all up in a div */}
<div className="container">
<div className="box">
<div className="row">
<div className="col-lg-12 col-sm-12 text-center">
<br />
<div>
<Progress animated value="33">33%</Progress>
</div>
<br/>
<span className="title text-center">Step 2 of 6</span>
<h2 className="text-center">Address</h2>
</div>
</div>
<form className="form" onSubmit={handleSubmit}>
<hr />
<b className="formHeading"><i className='fa fa-home'></i> Hey {firstName}, what's your home address?</b>
<br />
<br />
<div className="col-md-6 mx-auto">
<Field name="streetAddress" type="text" component={RenderField} label="Street Address" validate={[requiredStreetAddress, validStreetAddress]} />
<br />
</div>
<div className="col-md-6 mx-auto">
<Field name="aptUnit" type="text" component={RenderField} label="Apt/Unit" />
<br />
</div>
<div className="col-md-6 mx-auto">
<div className="form-row">
<div className="col-md-8">
<Field name="city" type="text" component={RenderField} readonly="true" label="City" validate={[requiredCity, validCity]} />
</div>
<div className="col-md-4">
<Field name="state" type="text" component={renderStateSelector} label="State" validate={requiredState} />
<br />
</div>
</div>
</div>
<div className="col-md-6 mx-auto">
<Field name="zipCode" type="text" value={zipCode} component={zipField} readonly="true" label="Zip Code" validate={validZipCode} />
<br />
</div>
<form previousPage={this.props.previousPage}>
<button type="submit" id="nextBtn" className="btn btn-primary form-control">Next</button>
<button type="submit" id="backBtn" onClick={previousPage} className="btn btn-light form-control">Back</button>
<br />
</form>
{/*End of Form */}
</form>
</div>
<Footer />
</div>
</Fragment>
);
}
}
Address = reduxForm({
form: 'insurance',
destroyOnUnmount: false,
forceUnregisterOnUnmount: true,
})(Address);
const selector = formValueSelector('insurance')
Address = connect(state => {
const zipCode = selector(state, 'zipCode');
const firstName = selector(state, 'firstName');
return {
zipCode,
firstName,
city
}
})(Address)
export default Address;
Я очень новичок в react, поэтому пытаюсь учиться по ходу дела
Комментарии:
1. Пара советов: используйте функции со стрелками, чтобы вам не приходилось напрямую связывать функции, а Fragment также можно записать как
<>
и</>
. Добавлен тег «redux-form», чтобы знакомым людям было легче найти ваш вопрос2. Я бы ответил на ваш вопрос, но я болен, и у меня недостаточно внимания, чтобы полностью распутать это… но похоже, что свойство defaultProps — это, вероятно, то, что вы ищете.
Ответ №1:
При вызове initialize
поведение по умолчанию redux-form
заключается в очистке формы и инициализации только тех значений, которые вы туда передаете. Чтобы сохранить другие значения, вам нужно использовать свойство keepDirtyOnReinitialize: true
и enableReinitialize: true
Кстати, насколько я вижу, вам не нужно вызывать initialize на componentDidMount
. Вы можете передать в свою форму (что означает возврат свойства из mapStateToProps
), которая вызывается initialValues
, заполненную city, zip, FirstName…
Дополнительная информация приведена в документах API по reduxForm
ссылке