[英]Material UI Autocomplete using previous state options
I'm trying to suggest data using the autocomplete component based on 2 queries that fetch data from GraphQL.我正在尝试使用基于从 GraphQL 获取数据的 2 个查询的自动完成组件来建议数据。
const handleSearchChange = (evt, newInputValue) => {
const {
agentsEmail,
prefix,
appsName,
role,
fromDate,
toDate,
} = this.props;
console.log("handle Search Change")
this.setState({ userInput: evt.target.value });
if (newInputValue.length > 0) {
this.setState({ open: true });
setTimeout(() => { this.prepareFilterData(appsName, agentsEmail, prefix, role, fromDate, toDate); }, 500);
} else {
this.setState({ open: false });
}
}
const handleSelection = (evt, evtSelection, reason) => {
console.log(reason, "REASON handle Selection")
this.setState({ selection: evtSelection });
/* map over selection and for each element push to listings the element.id
to build the list of ids to be used by the seearch button handle event */
this.state.selection.map( (selection) => listings.push(selection.id))
console.log(this.state.selection, "SELECTION")
}
<Autocomplete
id="listings-filter"
multiple
open={this.state.open}
onOpen={handleOpen}
onClose={() => this.setState({ open: false })}
options={filterList}
limitTags={4}
groupBy={(option) => option.key}
disableCloseOnSelect
onChange={handleSelection}
onInputChange={handleSearchChange}
getOptionLabel={(option) => option.value}
renderOption={(option, { selected }) => (
<React.Fragment>
<Checkbox
icon={icon}
checkedIcon={checkedIcon}
style={{ marginRight: 8 }}
checked={selected}
/>
{option.value}
</React.Fragment>
)}
renderInput={(params) => (
<TextField {...params} label="Search listings by" placeholder="Address, MLS" />
)}
/>
I'm using a class component, and the options are a list I formatted to allow them to be grouped with the Autocomplete component, but it is always using a previous state of the options.我正在使用类组件,选项是我格式化的列表,以允许它们与自动完成组件分组,但它始终使用选项的先前状态。 for example: I type ca on the input and it fetches 100 values, but it uses that 100 values when I blur the input which clears the input and it loads the 100 fields.
例如:我在输入上键入ca并获取 100 个值,但是当我模糊清除输入并加载 100 个字段的输入时,它使用这 100 个值。 then when I type something else the empty options got loaded.
然后当我输入其他内容时,空选项被加载。 I always need to do +1 change event to got the actual options list, I tried setting to false the clearOnBlur property which didn't solve the issue because since the change event is not fired when blurring the input it never update the state (+1).
我总是需要做 +1 更改事件来获取实际的选项列表,我尝试将clearOnBlur属性设置为 false 没有解决问题,因为由于在模糊输入时未触发更改事件,因此它永远不会更新状态(+ 1)。 Any idea what could be causing this?
知道是什么原因造成的吗? Thanks in advice Here a animated example of my issue:
感谢建议 这是我的问题的动画示例:
EDIT: This behavior also happen when deleting the selected options or selecting them, if I select one of the options the change event reflects an empty list, when I select a second one it reflect just the first I selected.编辑:删除所选选项或选择它们时也会发生这种行为,如果我选择其中一个选项,则更改事件反映一个空列表,当我选择第二个选项时,它仅反映我选择的第一个。
This is the function I use to format and update the filterList I fetch the data with the fetchMls and fetchAddresses then using the mergeFilterData I update the filter list used on the options property这是我用来格式化和更新filterList的函数我使用 fetchMls 和 fetchAddresses 获取数据然后使用mergeFilterData我更新选项属性上使用的过滤器列表
prepareFilterData = async (appsName, agentsEmail, prefix, role, fromDate, toDate) => {
await this.fetchMls(appsName, agentsEmail, prefix, role, fromDate, toDate);
await this.fetchAddresses(appsName, agentsEmail, prefix, role, fromDate, toDate);
this.setState({
filterList: mergeFilterData(this.state.fetchedAddresses, this.state.fetchedMls, [])
});
console.log(this.state.filterList, "FINAL DATA")
/* this.setState({
filteredList: handleListChange(userInput, listingsList, 0.5),
}); */
}
EDIT2: Here is one of the functions I use to fetch the data, when the data is fetched is formated and saved on a state to be used. EDIT2:这是我用来获取数据的函数之一,当获取数据时,它被格式化并保存在要使用的状态上。
fetchMls = async (appsName, agentsEmail, prefix, role, fromDate, toDate) => {
const enumerationAppName = appsName.map((appName) => appName.enumeration);
const listAgents = agentsEmail.map((agent) => agent.name || agent);
console.log(this.state.userInput, "USER INPUT ON FETCH MLS")
const query = {
query: GET_LISTINGS_BY_MLS_PREFIX_QUERY,
variables: {
appsName: enumerationAppName,
agentsEmail: listAgents,
prefix,
fromDate: formatDate(fromDate),
toDate: formatDate(toDate),
mlsPrefix: this.state.userInput || "1",
},
};
applicationClient
.query(query)
.then((response) => {
if (response) {
if (!isEmpty(response.data.getListingsByMlsPrefix.data)) {
const result = response.data.getListingsByMlsPrefix.data.map(
(listing) => listing
);
const formatedMls = formatMls(result);
this.setState({ fetchedMls: formatedMls });
}
}
})
.catch((err) => {
this.setState({ fetchedMls: [] });
});
};
If you need to process data after state updates, the best way is on callback function:如果您需要在状态更新后处理数据,最好的方法是使用回调函数:
const handleSearchChange = (evt, newInputValue) => {
const {
agentsEmail,
prefix,
appsName,
role,
fromDate,
toDate,
} = this.props;
console.log("handle Search Change")
this.setState({
userInput: newInputValue,
open: newInputValue > 0
});
if (newInputValue.length > 0) {
setTimeout(() => { this.prepareFilterData(appsName, agentsEmail, prefix, role, fromDate, toDate); }, 500);
}
}
const handleSelection = (evt, evtSelection, reason) => {
console.log(reason, "REASON handle Selection")
this.setState({ selection: evtSelection }, ()=> {
this.state.selection.map( (selection) => listings.push(selection.id))
console.log(this.state.selection, "SELECTION")
});
/* map over selection and for each element push to listings the element.id
to build the list of ids to be used by the seearch button handle event */
}
I don't know what is in this.fetchMls and this.fetchAddresses functions, but I recommend you to get the data directly, something like this:我不知道 this.fetchMls 和 this.fetchAddresses 函数中是什么,但我建议您直接获取数据,如下所示:
prepareFilterData = async (appsName, agentsEmail, prefix, role, fromDate, toDate) => {
const fetchedAddresses = await this.fetchMls(appsName, agentsEmail, prefix, role, fromDate, toDate);
const fetchedMls = await this.fetchAddresses(appsName, agentsEmail, prefix, role, fromDate, toDate);
this.setState({
filterList: mergeFilterData(fetchedAddresses, fetchedMls, [])
}, ()=> console.log(this.state.filterList, "FINAL DATA"));
}
I hope this help you ;)我希望这对你有帮助;)
该问题与材料 UI 组件无关,问题与我正在获取的数据有关,因为我正在获取 3 个不同的查询,我遇到了竞争条件错误,所以我通过使用 Promises.all 解决所有承诺来解决它() 如果对任何人有用 ;)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.