我无法显示我的自动建议。 在控制台中观察到我的数据可用,并且我使用“建议”道具通过Material UI AutoComplete组件功能here将其发送到了此组件,我试图设置自己的选项,并且随着我键入以下内容而改变它是在父组件中处理的,但是设置值似乎并不能反映或提出我的建议。我很困扰。我的代码在下面。
import React, { FunctionComponent, FormEvent, ChangeEvent } from "react";
import { Grid, TextField, Typography } from "@material-ui/core";
import { CreateProjectModel, JobModel } from "~/Models/Projects";
import ErrorModel from "~/Models/ErrorModel";
import Autocomplete from "@material-ui/lab/Autocomplete";
type CreateProjectFormProps = {
model: CreateProjectModel;
errors: ErrorModel<CreateProjectModel>;
onChange: (changes: Partial<CreateProjectModel>) => void;
onSubmit?: () => Promise<void>;
suggestions: JobModel[];
};
const CreateProjectForm: FunctionComponent<CreateProjectFormProps> = ({
model,
errors,
onChange,
onSubmit,
suggestions,
}) => {
const [open, setOpen] = React.useState(false);
const [options, setOptions] = React.useState<JobModel[]>([]);
const loading = open && options.length === 0;
const [inputValue, setInputValue] = React.useState('');
React.useEffect(() => {
let active = true;
if (!loading) {
return undefined;
}
(async () => {
if (active) {
setOptions(suggestions);
}
})();
return () => {
active = false;
};
}, [loading]);
React.useEffect(() => {
if (!open) {
setOptions([]);
}
}, [open]);
const submit = async (event: FormEvent) => {
event.preventDefault();
event.stopPropagation();
await onSubmit();
};
const change = (name: string) => (event: ChangeEvent<HTMLInputElement>) => {
setInputValue(event.target.value);
onChange({
[name]: event.target.value,
});
};
const getFieldProps = (id: string, label: string) => {
return {
id,
label,
helperText: errors[id],
error: Boolean(errors[id]),
value: model[id],
onChange: change(id),
};
};
return (
<Autocomplete
{...getFieldProps}
open={open}
onOpen={() => {
setOpen(true);
}}
onClose={() => {
setOpen(false);
}}
getOptionSelected={(option, value) => option.id === value.id}
getOptionLabel={(option) => option.id}
options={options}
loading={loading}
autoComplete
includeInputInList
renderInput={(params) => (
<TextField
{...getFieldProps("jobNumber", "Job number")}
required
fullWidth
autoFocus
margin="normal"
/>
)}
renderOption={(option) => {
return (
<Grid container alignItems="center">
<Grid item xs>
{options.map((part, index) => (
<span key={index}>
{part.id}
</span>
))}
<Typography variant="body2" color="textSecondary">
{option.name}
</Typography>
</Grid>
</Grid>
);
}}
/>
);
};
export default CreateProjectForm;
我的建议数据示例如下:
[{"id":"BR00001","name":"Aircrew - Standby at home base"},{"id":"BR00695","name":"National Waste"},{"id":"BR00777B","name":"Airly Monitor Site 2018"},{"id":"BR00852A","name":"Cracow Mine"},{"id":"BR00972","name":"Toowoomba Updated"},{"id":"BR01023A","name":"TMRGT Mackay Bee Creek"},{"id":"BR01081","name":"Newman Pilot Job (WA)"},{"id":"BR01147","name":"Lake Vermont Monthly 2019"},{"id":"BR01158","name":"Callide Mine Monthly Survey 2019"},{"id":"BR01182","name":"Lake Vermont Quarterly 2019 April"}]
答案 0 :(得分:4)
代码中的问题是您使用的useEffects。
在下面的useEffect中,实际上是最初将选项设置为空数组。那是因为您没有打开自动完成功能,并且效果也在初始安装上运行。同样,由于您是在另一种useEffect中设置选项,因此代码只能在加载状态更新时才起作用,而您还没有打开自动完成下拉菜单。
关闭一次后,状态将更新为空,您将不再看到建议。
React.useEffect(() => {
if (!open) {
setOptions([]);
}
}, [open]);
解决方案很简单。您不需要为选项保留本地状态,而可以使用来自props的值suggestions
您只需要保持打开状态
const CreateProjectForm: FunctionComponent<CreateProjectFormProps> = ({
model,
errors,
onChange,
onSubmit,
suggestions,
}) => {
const [open, setOpen] = React.useState(false);
const loading = open && suggestions.length === 0;
const [inputValue, setInputValue] = React.useState('');
const submit = async (event: FormEvent) => {
event.preventDefault();
event.stopPropagation();
await onSubmit();
};
const change = (name: string) => (event: ChangeEvent<HTMLInputElement>) => {
setInputValue(event.target.value);
onChange({
[name]: event.target.value,
});
};
const getFieldProps = (id: string, label: string) => {
return {
id,
label,
helperText: errors[id],
error: Boolean(errors[id]),
value: model[id],
onChange: change(id),
};
};
return (
<Autocomplete
{...getFieldProps}
open={open}
onOpen={() => {
setOpen(true);
}}
onClose={() => {
setOpen(false);
}}
getOptionSelected={(option, value) => option.id === value.id}
getOptionLabel={(option) => option.id}
options={suggestions}
loading={loading}
autoComplete
includeInputInList
renderInput={(params) => (
<TextField
{...getFieldProps("jobNumber", "Job number")}
required
fullWidth
autoFocus
margin="normal"
/>
)}
renderOption={(option) => {
return (
<Grid container alignItems="center">
<Grid item xs>
{options.map((part, index) => (
<span key={index}>
{part.id}
</span>
))}
<Typography variant="body2" color="textSecondary">
{option.name}
</Typography>
</Grid>
</Grid>
);
}}
/>
);
};
export default CreateProjectForm;
答案 1 :(得分:1)
我注意到您的代码存在一些问题,正在调用getFieldProps
而不使用id或name参数,这会导致页面无法加载。更重要的是,传递和使用道具时应考虑遵循autocomplete docs。例如:
renderInput={(params) => <TextField {...params} label="Controllable" variant="outlined" />}
我问了几个问题,请让我知道何时可以得到这些答案,以便我解决可能出现的所有问题。
Q1。用户输入应该从您建议中的name属性还是ID提供相关的匹配项?对于前。如果我输入“ lake”,是否要显示2019年4月的佛蒙特湖季刊BRO1182作为匹配项?
第二季度。您想如何解决错误情况?我看到您有一个错误模型,但是不确定发生错误时希望如何使用它来设置自动填充样式
Q3。我们是否缺少提交按钮?我看到了onSubmit
函数,但是我们的代码中没有使用它。
Q4。为什么需要打开状态和加载状态是特定原因?
以下是我到目前为止试图从用户输入中显示相关匹配项的内容
import React, { FunctionComponent, FormEvent, ChangeEvent } from "react";
import { Grid, TextField, Typography } from "@material-ui/core";
import { CreateProjectModel, JobModel } from "~/Models/Projects";
import ErrorModel from "~/Models/ErrorModel";
import Autocomplete from "@material-ui/lab/Autocomplete";
type CreateProjectFormProps = {
model: CreateProjectModel;
errors: ErrorModel<CreateProjectModel>;
onChange: (changes: Partial<CreateProjectModel>) => void;
onSubmit?: () => Promise<void>;
suggestions: JobModel[];
};
const CreateProjectForm: FunctionComponent<CreateProjectFormProps> = ({
model,
errors,
// mock function for testing
// consider a better name like selectChangeHandler
onChange = val => console.log(val),
// consider a better name like submitJobFormHandler
onSubmit,
suggestions: options = [
{ id: "BR00001", name: "Aircrew - Standby at home base" },
{ id: "BR00695", name: "National Waste" },
{ id: "BR00777B", name: "Airly Monitor Site 2018" },
{ id: "BR00852A", name: "Cracow Mine" },
{ id: "BR00972", name: "Toowoomba Updated" },
{ id: "BR01023A", name: "TMRGT Mackay Bee Creek" },
{ id: "BR01081", name: "Newman Pilot Job (WA)" },
{ id: "BR01147", name: "Lake Vermont Monthly 2019" },
{ id: "BR01158", name: "Callide Mine Monthly Survey 2019" },
{ id: "BR01182", name: "Lake Vermont Quarterly 2019 April" }
]
}) => {
const [value, setValue] = React.useState<JobModel>({});
const loading = open && options.length === 0;
// this pc of code is not used, why?
const submit = async (event: FormEvent) => {
event.preventDefault();
event.stopPropagation();
await onSubmit();
};
const handleChange = (_: any, value: JobModel | null) => {
setValue(value);
onChange({
[value.name]: value.id
});
};
// consider passing in props instead
const getFieldProps = (id: string, label: string) => {
return {
id,
label,
// not sure what this is
helperText: errors[id],
// not sure what this is
error: Boolean(errors[id]),
value: model[id],
onChange: change(id)
};
};
return (
<Autocomplete
id="placeholder-autocomplete-input-id"
// for selection, use value see docs for more detail
value={value}
onChange={handleChange}
getOptionSelected={(option, value) => option.id === value.id}
getOptionLabel={option => option.id}
options={options}
loading={loading}
autoComplete
includeInputInList
renderInput={params => (
// spreading the params here will transfer native input attributes from autocomplete
<TextField
{...params}
label="placeholder"
required
fullWidth
autoFocus
margin="normal"
/>
)}
renderOption={option => (
<Grid container alignItems="center">
<Grid item xs>
<span key={option}>{option.id}</span>
<Typography variant="body2" color="textSecondary">
{option.name}
</Typography>
</Grid>
</Grid>
)}
/>
);
};
export default CreateProjectForm;
点击下面的按钮,您可以在我的代码和框中看到正在运行的代码
答案 2 :(得分:0)
如果我理解您的代码并正确发布,您就可以-
React.useEffect(() => {
let active = true;
if (!loading) {
return undefined;
}
(async () => {
if (active) {
setOptions(suggestions);
}
})();
return () => {
active = false;
};
}, [loading]);
每次运行并更新options
,但事实是,[loading]
依赖项设置为
const loading = open && suggestions.length === 0;
并且不会触发更改。
考虑这样做-
const loading = useLoading({open, suggestions})
const useLoading = ({open, suggestions}) => open && suggestions.length === 0;