#javascript #reactjs #setstate #formik #yup
#javascript #reactjs #setstate #formik #ага
Вопрос:
Используя Formik для проверки некоторых полей, если значение состояния равно true, я хочу, чтобы значение одного поля копировалось в значение другого.
Например, значение mainAddress
, в которое нужно скопировать address
.
Существует переменная состояния, setAddress
для которой установлено значение false, но ее можно изменить на true при нажатии флажка.
Когда для этой переменной установлено значение true, я хочу, чтобы значение mainAddress
копировалось в address
Это код, который отлично работает без копирования этого значения:
import React from 'react';
import { Formik, Form, Field } from 'formik';
import { Input, Button, Label, Grid } from 'semantic-ui-react';
import * as Yup from 'yup';
import { Creators } from '../../../actions';
import './CreateCompanyForm.scss';
class CreateCompanyForm extends React.PureComponent {
constructor(props) {
super(props);
this.state = { // state variables
address: '',
mainAddress: '',
setAddress: false,
};
}
handleSubmit = values => {
// create company
};
toggleAddress = () => { // it toggles the value of setAddress
this.setState(prevState => ({
setAddress: !prevState.setAddress,
}));
};
render() {
const initialValues = { // the address and mainAddress are set to '' at the start
address: '',
mainAddress: '',
};
const validationSchema = Yup.object({
address: Yup.string().required('error'),
mainAddress: Yup.string().required('error'),
});
return (
<>
<Button type="submit" form="amazing"> // button for submit
Create company
</Button>
<Formik
htmlFor="amazing"
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={values => this.handleSubmit(values)}>
{({ values, errors, touched, setValues, setFieldValue }) => (
<Form id="amazing">
<Grid>
<Grid.Column> // mainAddress value
<Label>Main Address</Label>
<Field name="mainAddress" as={Input} />
</Grid.Column>
<Grid.Column> // address value
<Label>Address</Label>
<Field name="address" as={Input} />
<div>
{this.state.setAddress // here is how I've tried to set that value
? values.address.setFieldValue(values.mainAddress)
: console.log('nope')}
{touched.address amp;amp; errors.address ? errors.address : null}
</div>
</Grid.Column>
</Grid>
<Checkbox
label="Use same address"
onClick={() => this.toggleAddress()}
/>
</Form>
)}
</Formik>
</>
);
}
}
Итак, я пробовал другие способы ее решения, но безуспешно. Теперь в коде это:
{this.state.setAddress
? values.address.setFieldValue(values.mainAddress)
: console.log('nope')}
Другой был: (this.state.setAddress ? values.address = values.mainAddress)
Ни один из них не работает. Возможно ли получить значение из values.mainAddress
и скопировать его в values.address
? Или на его ввод?
Ответ №1:
Вы можете соответствующим образом переписать компонент поля для адреса.
<Field name="address">
{({
field, // { name, value, onChange, onBlur }
}) => {
values.address = values.mainAddress;
return (
<div>
<input
{...field}
type="text"
placeholder="Address"
/>
</div>
);
}}
</Field>
Здесь мы устанавливаем значение поля адреса в values.mainAddress если установлен флажок setAdress, иначе мы позволим formik value заполнить его.
Вот рабочий код codesandbox — https://codesandbox.io/s/fervent-tereshkova-sro93?file=/index.js
Комментарии:
1. Он работает для получения значения из
mainAddress
и копирования вaddress
. Однако я не могу отправить форму, потому что в ней указано, что она недействительна. Это происходит потому, что оно не обновляется дляvalues
объекта. Этот объект выглядит следующим образом:{ address: "", mainAddress: "mytext"}
. Есть ли способ обновить и это? Я пробовал, например:this.state.setAddress ? (values.mainAddress, values.address = values.mainAddress) : field.value }
но это не работает, ошибка:Arrow function should not return assignment
иAssignment to property of function parameter 'values'
2. Я обновил ответ. Пожалуйста, проверьте. Теперь это должно сработать. Я также обновил код codesandbox.
Ответ №2:
Formik также предоставляет объект values, который вы можете использовать для обновления значения адреса, аналогичного mainAddress. Просто укажите атрибут name для обоих полей ввода, а затем назначьте так — props.values.address = {…props.values.mainAddress}
Комментарии:
1. не могли бы вы расширить свой ответ, пожалуйста?
2. Поскольку вы деструктурировали значения из этого в своем коде
{({ values, errors, touched, setValues, setFieldValue })
, вы можете сделать это при срабатывании onClick внутри вашего флажка:onClick ={() => values.address = values.mainAddress}