首页 > 解决方案 > Material-UI CloseIcon not showing in Autocomplete

问题描述

I am trying to work using the Autocomplete component using Material-UI, and for some reason, the close icon does not show when I update some text.

I split the Autocomplete component up by display and with a wrapper that actually makes the API request on text change. I have tried specifying the closeIcon prop, but cannot get it to show up.

Display Component:

import React from 'react';
import { faPodcast, faSearch, faUser } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Grid } from '@material-ui/core';
import Box from '@material-ui/core/Box';
import InputAdornment from '@material-ui/core/InputAdornment';
import TextField from '@material-ui/core/TextField';
import Typography from '@material-ui/core/Typography';
import { Autocomplete } from '@material-ui/lab';

function SearchBarDisplay({ options = [], onChange, onSelectValue, text }) {
    function getOptionLabel(option) {
        if (option.name) {
            return option.name;
        } else if (option.username) {
            return option.username;
        } else if (option.type === 'advanced') {
            return option.text;
        } else {
            return null;
        }
    }

    function renderOption(name, username, type) {
        if (name) {
            return (
                <Grid container alignItems="center" wrap="nowrap">
                    <Box mr={1}>
                        <FontAwesomeIcon icon={faPodcast} />
                    </Box>
                    <Typography noWrap>{name}</Typography>
                </Grid>
            );
        } else if (username) {
            return (
                <Grid container alignItems="center" wrap="nowrap">
                    <Box mr={1}>
                        <FontAwesomeIcon icon={faUser} />
                    </Box>
                    <Typography noWrap>{username}</Typography>
                </Grid>
            );
        } else if (type === 'advanced') {
            return (
                <Grid container alignItems="center" wrap="nowrap">
                    <Box mr={1}>
                        <FontAwesomeIcon icon={faSearch} />
                    </Box>
                    <Typography
                        noWrap={true}
                        color="textSecondary">{`See more results for "${text}"`}</Typography>
                </Grid>
            );
        } else {
            return null;
        }
    }

    return (
        <Autocomplete
            id="autocomplete"
            options={text.replace(/\s/g, '').length ? options : []}
            popupIcon={null}
            getOptionSelected={(option, value) => option._id === value._id}
            getOptionLabel={(option) => getOptionLabel(option)}
            onChange={(event, value) => onSelectValue(value)}
            onInputChange={(event, value) => onChange(value)}
            renderOption={({ name, username, type }) => renderOption(name, username, type)}
            renderInput={(params) => (
                <TextField
                    {...params}
                    placeholder="Search for podcasts or TapTapers"
                    margin="normal"
                    variant="outlined"
                    InputProps={{
                        ...params.InputProps,
                        startAdornment: (
                            <InputAdornment position="start">
                                <FontAwesomeIcon icon={faSearch} />
                            </InputAdornment>
                        )
                    }}
                />
            )}
        />
    );
}

export default SearchBarDisplay;

Wrapper to make API requests and pass in options/current text value:

import React, { useEffect, useMemo, useState } from 'react';
import axios from 'axios';
import { debounce } from 'lodash';
import { useRouter } from 'next/router';

import SearchBarDisplay from './display';

function SearchBar() {
    const router = useRouter();
    const [options, setOptions] = useState([]);
    const [text, setText] = useState('');

    async function getSearch(text) {
        await axios.get(`/api/search/${text}`).then(({ data }) => {
            if (Object.keys(data).length === 0 || text.trim().length === 0) {
                setOptions([]);
            } else {
                setOptions([...data, ...[{ type: 'advanced', text: text }]]);
            }
        });
    }

    function routeOnSubmit(value) {
        const { username, _id, name, type, text } = value || {};
        if (username) {
            router.push({
                pathname: '/users/[id]',
                query: { id: _id }
            });
        } else if (name) {
            router.push({
                pathname: '/podcasts/[id]',
                query: { id: _id }
            });
        } else if (type === 'advanced') {
            router.push({
                pathname: 'search/advanced/[text]',
                query: { text }
            });
        }
    }

    const debouncedGetSearch = useMemo(() => debounce(getSearch, 500), []);

    useEffect(() => {
        if (text.replace(/\s/g, '').length) {
            debouncedGetSearch(text);
        } else {
            setOptions([]);
        }
    }, [text, debouncedGetSearch]);

    return (
        <SearchBarDisplay
            options={options}
            onSelectValue={(value) => routeOnSubmit(value)}
            text={text}
            onChange={(value) => setText(value)}
        />
    );
}

export default SearchBar;


标签: reactjsmaterial-ui

解决方案


I was able to fix this! I wanted the close icon to appear when you typed, and I needed to pass in the freeSolo prop as per the Material-UI documentation.


推荐阅读