reactjs - 如何使用 Formik 和 Material-UI 获得价值可重用的自动完成组件
问题描述
我有一个可重用的自动完成组件,我需要获取选定的对象,但我无法在组件之外访问此信息。
如何访问表单上的选定对象?
我感谢你的帮助!
自动完成:
import * as React from "react";
import { FieldProps, getIn } from "formik";
import { TextField, CircularProgress } from "@material-ui/core";
import MuiAutocomplete, {
createFilterOptions
} from "@material-ui/lab/Autocomplete";
const NewAutocomplete: React.FC<
FieldProps & {
label?: string,
options: Array<{ label: string, value: number }>
}
> = ({ textFieldProps, field, form, label, options, isLoading, ...props }) => {
const filterOptions = createFilterOptions({
matchFrom: "start",
limit: 500
});
const errorText =
getIn(form.touched, field.name) && getIn(form.errors, field.name);
const valueInit = [
{
value: 0,
label: ""
}
];
return (
<MuiAutocomplete
{...props}
{...field}
filterOptions={filterOptions}
options={[...valueInit, ...options]}
getOptionLabel={(option) => (option ? option.label : "")}
getOptionSelected={(option, value) => option.value === value?.value}
loading={isLoading}
value={field.value}
onChange={(e, value) => {
form.setFieldValue(field.name, value);
//console.log(value);
}}
renderInput={(props) => (
<>
<TextField
{...props}
{...textFieldProps}
label={label}
helperText={errorText?.value || errorText}
error={!!errorText}
InputProps={{
...props.InputProps,
endAdornment: (
<React.Fragment>
{isLoading ? (
<CircularProgress color="primary" size={20} />
) : null}
{props.InputProps.endAdornment}
</React.Fragment>
)
}}
/>
</>
)}
/>
);
};
export default NewAutocomplete;
形式:
import { Grid } from "@material-ui/core";
import { Field, Form, Formik } from "formik";
import Autocomplete from "./component/Autocomplete";
const listFilms = [
{ label: "The Shawshank Redemption", value: 1 },
{ label: "The Godfather", value: 2 },
{ label: "The Godfather: Part II", value: 3 },
{ label: "The Dark Knight", value: 4 }
];
const initialValues = {
film: {
label: "",
value: 0
}
};
export default function App() {
return (
<div className="App">
<Formik initialValues={initialValues}>
{function Render({ errors, touched, isSubmitting, setFieldValue }) {
return (
<Form id="form">
<Grid container direction="row">
<Grid item xs={12}>
<Field
name="film"
component={Autocomplete}
label="Film"
options={listFilms}
onChange={(e, value) => {
console.log(value);
}}
textFieldProps={{
fullWidth: true,
margin: "dense",
variant: "outlined",
autoFocus: true
}}
/>
</Grid>
</Grid>
</Form>
);
}}
</Formik>
</div>
);
}
解决方案
我设法解决了通过道具传递值:setFieldValue
自动完成:
import * as React from "react";
import { FieldProps, getIn } from "formik";
import { TextField, CircularProgress } from "@material-ui/core";
import MuiAutocomplete, {
createFilterOptions
} from "@material-ui/lab/Autocomplete";
const NewAutocomplete: React.FC<
FieldProps & {
label?: string,
options: Array<{ label: string, value: number }>
}
> = ({
textFieldProps,
field,
form,
label,
options,
isLoading,
setFieldValue,
...props
}) => {
const filterOptions = createFilterOptions({
matchFrom: "start",
limit: 500
});
const errorText =
getIn(form.touched, field.name) && getIn(form.errors, field.name);
const valueInit = [
{
value: 0,
label: ""
}
];
return (
<MuiAutocomplete
{...props}
{...field}
filterOptions={filterOptions}
options={[...valueInit, ...options]}
getOptionLabel={(option) => (option ? option.label : "")}
getOptionSelected={(option, value) => option.value === value?.value}
loading={isLoading}
value={field.value}
onChange={(e, value) => {
form.setFieldValue(field.name, value);
if (setFieldValue) {
setFieldValue(value);
}
}}
renderInput={(props) => (
<>
<TextField
{...props}
{...textFieldProps}
label={label}
helperText={errorText?.value || errorText}
error={!!errorText}
InputProps={{
...props.InputProps,
endAdornment: (
<React.Fragment>
{isLoading ? (
<CircularProgress color="primary" size={20} />
) : null}
{props.InputProps.endAdornment}
</React.Fragment>
)
}}
/>
</>
)}
/>
);
};
export default NewAutocomplete;
形式:
import { Grid } from "@material-ui/core";
import { Field, Form, Formik } from "formik";
import { useState } from "react";
import Autocomplete from "./component/Autocomplete";
const listFilms = [
{ label: "The Shawshank Redemption", value: 1 },
{ label: "The Godfather", value: 2 },
{ label: "The Godfather: Part II", value: 3 },
{ label: "The Dark Knight", value: 4 }
];
const initialValues = {
film: {
label: "",
value: 0
}
};
export default function App() {
const [autocompleteValue, setAutocompleteValue] = useState(null);
console.log(autocompleteValue);
return (
<div className="App">
<Formik initialValues={initialValues}>
{function Render({ formik, values, setFieldValue }) {
return (
<Form id="form">
<Grid container direction="row">
<Grid item xs={12}>
<Field
name="film"
component={Autocomplete}
label="Film"
options={listFilms}
textFieldProps={{
fullWidth: true,
margin: "dense",
variant: "outlined",
autoFocus: true
}}
setFieldValue={setAutocompleteValue}
/>
</Grid>
</Grid>
</Form>
);
}}
</Formik>
</div>
);
}
控制台日志:
{label: "The Godfather", value: 2}
推荐阅读
- java - 尝试为 Java1.7 启用 TLSv1.2 时,TLS 握手失败。请启发我
- docker - 描述性管道和作为代理的 docker 工具
- android-studio - 我已经被困在“运行 Gradle 任务'assembleDebug'..”几个小时了
- python - Docker 容器以不明确的方式影响撰写环境中的其他人
- algorithm - 银行家的算法 - 如果工作少于需要,我可以将资源分配给进程吗
- python-3.x - 二维列表对一
- angular - 如何访问 person.service.ts 中的 _angularFireAuth.auth.currentUser.email?
- python - 带有管道的python子进程
- c# - 用于连接到 MS Office 365 Graph API 的 Azure 客户端的代码
- splunk - Splunk 限制 stats list() 函数返回的结果