React-select 与 Formik 不更新 select 字段但做其他一切
React-select with Formik not updating select field but does everything else
React-Select with Formik 没有在 select componenet 中加载 selected 值,但我能够在表单提交和验证中获取值也适用于 Yup
这是相同的 codesandbox 演示 - https://codesandbox.io/s/wild-violet-fr9re
https://codesandbox.io/embed/wild-violet-fr9re?fontsize=14
import React, { Component } from "react";
import { Formik, Form, ErrorMessage } from "formik";
import * as Yup from "yup";
import Select from "react-select";
const debug = true;
class SelectForm extends Component {
constructor(props) {
super(props);
this.state = {
stateList: [],
stateCity: "",
selectedState: "",
citiesToLoad: []
};
}
handleState(opt) {
console.log(opt.value);
let citiesList = [];
Object.keys(this.state.stateCity).forEach(key => {
if (key === opt.value) {
this.state.stateCity[key].map((cityName, j) => {
citiesList.push(cityName);
});
}
});
this.setState({
selectedState: opt.value,
citiesToLoad: citiesList
});
}
handleMyCity(opt) {
console.log(opt.value);
}
componentDidMount() {
let stateLi = [];
fetch(`stateCity.json`)
.then(response => {
console.log(response);
return response.json();
})
.then(data => {
console.log(data);
for (let key in data) {
if (data.hasOwnProperty(key)) {
stateLi.push(key);
}
}
this.setState({ stateCity: data, stateList: stateLi });
})
.catch(err => {
console.log("Error Reading data " + err); // Do something for error here
});
}
render() {
const { selectedState, stateList, citiesToLoad } = this.state;
const newStateList = stateList.map(item => ({ label: item, value: item }));
const newCitiesToLoad = citiesToLoad.map(item => ({
label: item,
value: item
}));
return (
<div id="signupContainer" className="signinup-container">
<h3 className="mb-4"> Sign Up </h3>
<Formik
initialValues={{
state: selectedState,
city: ""
}}
validationSchema={Yup.object().shape({
state: Yup.string().required("Please select state."),
city: Yup.string().required("Please select city.")
})}
onSubmit={(values, { resetForm, setErrors, setSubmitting }) => {
setTimeout(() => {
console.log("Getting form values - ", values);
setSubmitting(false);
}, 500);
}}
enableReinitialize={true}
>
{props => {
const {
values,
touched,
dirty,
errors,
isSubmitting,
handleChange,
setFieldValue,
setFieldTouched
} = props;
return (
<Form id="signUpForm" className="signinupForm" noValidate>
<div className="form-group">
<label htmlFor="state" className="form-label">
State
</label>
<Select
name="state"
id="state"
onBlur={() => setFieldTouched("state", true)}
value={values.state}
onChange={(opt, e) => {
this.handleState(opt);
handleChange(e);
setFieldValue("state", opt.value);
}}
options={newStateList}
error={errors.state}
touched={touched.state}
/>
</div>
<div className="form-group">
<label htmlFor="city" className="form-label">
City
</label>
<Select
name="city"
id="city"
onBlur={() => setFieldTouched("city", true)}
value={values.city}
onChange={(opt, e) => {
this.handleMyCity(opt);
setFieldValue("city", opt.value);
}}
options={newCitiesToLoad}
/>
</div>
{isSubmitting ? (
<span className="loader-gif">
<img src={loading} alt="Loading..." />
</span>
) : null}
<button
type="submit"
className="btn btn-filled"
disabled={!dirty || isSubmitting}
>
Submit
</button>
{/*Submit */}
</Form>
);
}}
</Formik>
</div>
);
}
}
export default SelectForm;
在 select 从选择下拉列表中输入任何值后,我的 selected 值应该出现在 select 框中
react-select接受一个对象作为值所以你需要传递一个
的对象
let object = {
"label": "Andhra Pradesh",
"value": "Andhra Pradesh"
}
绕过值中的对象 selected 值出现在 select 框中
这是一个codesandbox演示https://codesandbox.io/s/floral-fire-8txrt
所以更新后的代码是
import React, { Component } from "react";
import { Formik, Form, ErrorMessage } from "formik";
import * as Yup from "yup";
import Select from "react-select";
const debug = true;
class SelectForm extends Component {
constructor(props) {
super(props);
this.state = {
stateList: [],
stateCity: "",
selectedState: "",
citiesToLoad: []
};
}
handleState(opt) {
console.log(opt.value);
let citiesList = [];
Object.keys(this.state.stateCity).forEach(key => {
if (key === opt.value) {
this.state.stateCity[key].map((cityName, j) => {
citiesList.push(cityName);
});
}
});
this.setState({
selectedState: opt,
citiesToLoad: citiesList
});
}
handleMyCity(opt) {
console.log(opt.value);
}
componentDidMount() {
let stateLi = [];
fetch(`stateCity.json`)
.then(response => {
console.log(response);
return response.json();
})
.then(data => {
console.log(data);
for (let key in data) {
if (data.hasOwnProperty(key)) {
stateLi.push(key);
}
}
this.setState({ stateCity: data, stateList: stateLi });
})
.catch(err => {
console.log("Error Reading data " + err); // Do something for error here
});
}
render() {
const { selectedState, stateList, citiesToLoad } = this.state;
const newStateList = stateList.map(item => ({ label: item, value: item }));
const newCitiesToLoad = citiesToLoad.map(item => ({
label: item,
value: item
}));
return (
<div id="signupContainer" className="signinup-container">
<h3 className="mb-4"> Sign Up </h3>
<Formik
initialValues={{
state: selectedState,
city: ""
}}
validationSchema={Yup.object().shape({
state: Yup.string().required("Please select state."),
city: Yup.string().required("Please select city.")
})}
onSubmit={(values, { resetForm, setErrors, setSubmitting }) => {
setTimeout(() => {
console.log("Getting form values - ", values);
setSubmitting(false);
}, 500);
}}
enableReinitialize={true}
>
{props => {
const {
values,
touched,
dirty,
errors,
isSubmitting,
handleChange,
setFieldValue,
setFieldTouched
} = props;
return (
<Form id="signUpForm" className="signinupForm" noValidate>
<div className="form-group">
<label htmlFor="state" className="form-label">
State
</label>
<Select
name="state"
id="state"
onBlur={() => setFieldTouched("state", true)}
value={values.state}
onChange={(opt, e) => {
this.handleState(opt);
handleChange(e);
setFieldValue("state", opt);
}}
options={newStateList}
error={errors.state}
touched={touched.state}
/>
</div>
<div className="form-group">
<label htmlFor="city" className="form-label">
City
</label>
<Select
name="city"
id="city"
onBlur={() => setFieldTouched("city", true)}
value={values.city}
onChange={(opt, e) => {
this.handleMyCity(opt);
setFieldValue("city", opt);
}}
options={newCitiesToLoad}
/>
</div>
{isSubmitting ? (
<span className="loader-gif">
<img src={loading} alt="Loading..." />
</span>
) : null}
<button
type="submit"
className="btn btn-filled"
disabled={!dirty || isSubmitting}
>
Submit
</button>
{/*Submit */}
</Form>
);
}}
</Formik>
</div>
);
}
}
export default SelectForm;
您正在 select setFieldValue("state", opt.value);
的 onchange 上设置字段值,因此您不需要为 <Select>
:
设置值
<Select
name="state"
id="state"
onBlur={() => setFieldTouched("state", true)}
onChange={(opt, e) => {
this.handleState(opt);
handleChange(e);
setFieldValue("state", opt.value);
}}
options={newStateList}
error={errors.state}
touched={touched.state}
/>
两者都有变化 <Select>
React-Select with Formik 没有在 select componenet 中加载 selected 值,但我能够在表单提交和验证中获取值也适用于 Yup
这是相同的 codesandbox 演示 - https://codesandbox.io/s/wild-violet-fr9re
https://codesandbox.io/embed/wild-violet-fr9re?fontsize=14
import React, { Component } from "react";
import { Formik, Form, ErrorMessage } from "formik";
import * as Yup from "yup";
import Select from "react-select";
const debug = true;
class SelectForm extends Component {
constructor(props) {
super(props);
this.state = {
stateList: [],
stateCity: "",
selectedState: "",
citiesToLoad: []
};
}
handleState(opt) {
console.log(opt.value);
let citiesList = [];
Object.keys(this.state.stateCity).forEach(key => {
if (key === opt.value) {
this.state.stateCity[key].map((cityName, j) => {
citiesList.push(cityName);
});
}
});
this.setState({
selectedState: opt.value,
citiesToLoad: citiesList
});
}
handleMyCity(opt) {
console.log(opt.value);
}
componentDidMount() {
let stateLi = [];
fetch(`stateCity.json`)
.then(response => {
console.log(response);
return response.json();
})
.then(data => {
console.log(data);
for (let key in data) {
if (data.hasOwnProperty(key)) {
stateLi.push(key);
}
}
this.setState({ stateCity: data, stateList: stateLi });
})
.catch(err => {
console.log("Error Reading data " + err); // Do something for error here
});
}
render() {
const { selectedState, stateList, citiesToLoad } = this.state;
const newStateList = stateList.map(item => ({ label: item, value: item }));
const newCitiesToLoad = citiesToLoad.map(item => ({
label: item,
value: item
}));
return (
<div id="signupContainer" className="signinup-container">
<h3 className="mb-4"> Sign Up </h3>
<Formik
initialValues={{
state: selectedState,
city: ""
}}
validationSchema={Yup.object().shape({
state: Yup.string().required("Please select state."),
city: Yup.string().required("Please select city.")
})}
onSubmit={(values, { resetForm, setErrors, setSubmitting }) => {
setTimeout(() => {
console.log("Getting form values - ", values);
setSubmitting(false);
}, 500);
}}
enableReinitialize={true}
>
{props => {
const {
values,
touched,
dirty,
errors,
isSubmitting,
handleChange,
setFieldValue,
setFieldTouched
} = props;
return (
<Form id="signUpForm" className="signinupForm" noValidate>
<div className="form-group">
<label htmlFor="state" className="form-label">
State
</label>
<Select
name="state"
id="state"
onBlur={() => setFieldTouched("state", true)}
value={values.state}
onChange={(opt, e) => {
this.handleState(opt);
handleChange(e);
setFieldValue("state", opt.value);
}}
options={newStateList}
error={errors.state}
touched={touched.state}
/>
</div>
<div className="form-group">
<label htmlFor="city" className="form-label">
City
</label>
<Select
name="city"
id="city"
onBlur={() => setFieldTouched("city", true)}
value={values.city}
onChange={(opt, e) => {
this.handleMyCity(opt);
setFieldValue("city", opt.value);
}}
options={newCitiesToLoad}
/>
</div>
{isSubmitting ? (
<span className="loader-gif">
<img src={loading} alt="Loading..." />
</span>
) : null}
<button
type="submit"
className="btn btn-filled"
disabled={!dirty || isSubmitting}
>
Submit
</button>
{/*Submit */}
</Form>
);
}}
</Formik>
</div>
);
}
}
export default SelectForm;
在 select 从选择下拉列表中输入任何值后,我的 selected 值应该出现在 select 框中
react-select接受一个对象作为值所以你需要传递一个
的对象let object = {
"label": "Andhra Pradesh",
"value": "Andhra Pradesh"
}
绕过值中的对象 selected 值出现在 select 框中
这是一个codesandbox演示https://codesandbox.io/s/floral-fire-8txrt
所以更新后的代码是
import React, { Component } from "react";
import { Formik, Form, ErrorMessage } from "formik";
import * as Yup from "yup";
import Select from "react-select";
const debug = true;
class SelectForm extends Component {
constructor(props) {
super(props);
this.state = {
stateList: [],
stateCity: "",
selectedState: "",
citiesToLoad: []
};
}
handleState(opt) {
console.log(opt.value);
let citiesList = [];
Object.keys(this.state.stateCity).forEach(key => {
if (key === opt.value) {
this.state.stateCity[key].map((cityName, j) => {
citiesList.push(cityName);
});
}
});
this.setState({
selectedState: opt,
citiesToLoad: citiesList
});
}
handleMyCity(opt) {
console.log(opt.value);
}
componentDidMount() {
let stateLi = [];
fetch(`stateCity.json`)
.then(response => {
console.log(response);
return response.json();
})
.then(data => {
console.log(data);
for (let key in data) {
if (data.hasOwnProperty(key)) {
stateLi.push(key);
}
}
this.setState({ stateCity: data, stateList: stateLi });
})
.catch(err => {
console.log("Error Reading data " + err); // Do something for error here
});
}
render() {
const { selectedState, stateList, citiesToLoad } = this.state;
const newStateList = stateList.map(item => ({ label: item, value: item }));
const newCitiesToLoad = citiesToLoad.map(item => ({
label: item,
value: item
}));
return (
<div id="signupContainer" className="signinup-container">
<h3 className="mb-4"> Sign Up </h3>
<Formik
initialValues={{
state: selectedState,
city: ""
}}
validationSchema={Yup.object().shape({
state: Yup.string().required("Please select state."),
city: Yup.string().required("Please select city.")
})}
onSubmit={(values, { resetForm, setErrors, setSubmitting }) => {
setTimeout(() => {
console.log("Getting form values - ", values);
setSubmitting(false);
}, 500);
}}
enableReinitialize={true}
>
{props => {
const {
values,
touched,
dirty,
errors,
isSubmitting,
handleChange,
setFieldValue,
setFieldTouched
} = props;
return (
<Form id="signUpForm" className="signinupForm" noValidate>
<div className="form-group">
<label htmlFor="state" className="form-label">
State
</label>
<Select
name="state"
id="state"
onBlur={() => setFieldTouched("state", true)}
value={values.state}
onChange={(opt, e) => {
this.handleState(opt);
handleChange(e);
setFieldValue("state", opt);
}}
options={newStateList}
error={errors.state}
touched={touched.state}
/>
</div>
<div className="form-group">
<label htmlFor="city" className="form-label">
City
</label>
<Select
name="city"
id="city"
onBlur={() => setFieldTouched("city", true)}
value={values.city}
onChange={(opt, e) => {
this.handleMyCity(opt);
setFieldValue("city", opt);
}}
options={newCitiesToLoad}
/>
</div>
{isSubmitting ? (
<span className="loader-gif">
<img src={loading} alt="Loading..." />
</span>
) : null}
<button
type="submit"
className="btn btn-filled"
disabled={!dirty || isSubmitting}
>
Submit
</button>
{/*Submit */}
</Form>
);
}}
</Formik>
</div>
);
}
}
export default SelectForm;
您正在 select setFieldValue("state", opt.value);
的 onchange 上设置字段值,因此您不需要为 <Select>
:
<Select
name="state"
id="state"
onBlur={() => setFieldTouched("state", true)}
onChange={(opt, e) => {
this.handleState(opt);
handleChange(e);
setFieldValue("state", opt.value);
}}
options={newStateList}
error={errors.state}
touched={touched.state}
/>
两者都有变化 <Select>