使用先前状态选项的材料UI自动完成

时间:2020-10-05 19:48:25

标签: reactjs material-ui

我正尝试根据2个从GraphQL提取数据的查询,使用自动完成组件来建议数据。


    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" />
            )}
          />

我正在使用类组件,并且选项是我格式化的列表,以使它们可以与“自动完成”组件进行分组,但始终使用选项的先前状态。例如: 我在输入上键入 ca ,它会获取100个值,但是当我模糊输入时会使用100个值,从而清除输入并加载100个字段。然后当我键入其他内容时,空选项被加载。我总是需要执行+1 change事件来获取实际的选项列表,我尝试设置为false的 clearOnBlur 属性无法解决问题,因为由于模糊输入时不会触发change事件它永远不会更新状态(+1)。 知道是什么原因造成的吗?谢谢建议 这是我的问题的动画示例: enter image description here

编辑:删除选定的选项或选择它们时,也会发生此行为,如果我选择一个选项,则change事件反映一个空列表,当我选择第二个选项时,它仅反映我选择的第一个。

这是我用来格式化和更新 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:这是在提取数据时将其格式化并保存在要使用的状态下的,我用来提取数据的功能之一。

  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: [] });
      });
  };

2 个答案:

答案 0 :(得分:0)

如果您需要在状态更新后处理数据,最好的方法是使用回调函数:

 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 */

}

我不知道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"));
       
      }

希望对您有所帮助;)

答案 1 :(得分:0)

问题与实质性的UI组件无关,问题与我正在获取的数据有关,因为我正在获取3个不同的查询,而我都遇到了竞争条件错误,因此我通过使用Promises.all()如果对任何人都有用;)