Adam Schwarcz
Adam Schwarcz

Reputation: 487

Material-UI useAutocomplete cannot access option in onChange

I don't know what I am doing wrong but I cannot access the option.slug from the object I receive from the API. I am trying to change pass a URL slug and change the route of my app. I am trying to do this using the onChange prop inside my useAutocomplete() definition.

Accessing the option.slug or any other property works well inside of my JSX structure. As you can see I am grabbing option.title and so on to render my list items which works well...

Instead of grabbing the actual slug I keep getting the route of "/components/undefined"

But when I try accessing the option.slug on the top level of my component in the useAutocomplete() definition it doesn't seem to work. Based on the original documentation though, that's the way to do it.

https://material-ui.com/components/autocomplete/#useautocomplete

export default function NavigationSearch({ onClose, results }) {
    const router = useRouter();

    const {
        getRootProps,
        getInputLabelProps,
        getInputProps,
        getListboxProps,
        getOptionProps,
        groupedOptions
    } = useAutocomplete({
        id: 'use-autocomplete-demo',
        options: results,
        getOptionLabel: (option) => option.title,
        onChange: (option) => router.push(`/components/${option.slug}`)
    });

    return (
        <React.Fragment>
            {/* 1. SEARCH INPUT */}
            <Container maxWidth="md" disableGutters>
                <Box display="flex" width="100%">
                    <motion.div
                        style={{ width: 'inherit' }}
                        initial="hidden"
                        animate="visible"
                        variants={animation}>
                        <Box display="flex" width="inherit">
                            <Search width="inherit" {...getRootProps()}>
                                <SearchIcon color="primary" />
                                <InputBase
                                    placeholder="Search for components, patterns..."
                                    style={{ color: 'inherit', width: 'inherit' }}
                                    autoFocus
                                    {...getInputProps()}
                                />
                            </Search>
                        </Box>
                    </motion.div>
                    <IconButton color="primary" onClick={onClose}>
                        <CloseIcon />
                    </IconButton>
                </Box>
            </Container>

            {/* SEARCH RESULTS */}
            <BackdropOverlay open={true} onClick={onClose}>
                <Container maxWidth="md" disableGutters>
                    {groupedOptions.length > 0 ? (
                        <Results>
                            <List
                                {...getListboxProps()}
                                subheader={
                                    <Box paddingX={2}>
                                        <Typography
                                            variant="overline"
                                            color="textSecondary"
                                            gutterBottom>
                                            Popular search results
                                        </Typography>
                                    </Box>
                                }>
                                {groupedOptions.map((option, index) => (
                                    <Item
                                        button
                                        key={option.title}
                                        {...getOptionProps({
                                            option,
                                            index
                                        })}>
                                        <Box
                                            display="flex"
                                            justifyContent="space-between"
                                            width="100%">
                                            <Box>
                                                <Typography color="textPrimary">
                                                    {option.title}
                                                </Typography>
                                                <Typography variant="caption" color="textSecondary">
                                                    {option.type}
                                                </Typography>
                                            </Box>
                                            <Box alignSelf="flex-end">
                                                <Typography variant="caption" color="textSecondary">
                                                    /components/button
                                                </Typography>
                                            </Box>
                                        </Box>
                                    </Item>
                                ))}
                            </List>
                        </Results>
                    ) : null}
                </Container>
            </BackdropOverlay>
        </React.Fragment>
    );
}

This is the API response that I store in the results prop:

0: {id: 1, title: "Button", slug: "button"}
1: {id: 2, title: "Switch", slug: "switch"}
2: {id: 3, title: "Tags", slug: "tags"}
3: {id: 4, title: "Checkbox", slug: "checkbox"}
4: {id: 5, title: "Toast", slug: "toast"}

Upvotes: 2

Views: 363

Answers (1)

NearHuscarl
NearHuscarl

Reputation: 81585

Autocomplete component uses useAutocomplete hook under the hood so they share the same API. In Autocomplete API. This is the signature of onChange:

function(event: object, value: T | T[], reason: string) => void

The second argument is the option value which is what you need here. So change your code to:

onChange: (_, option) => router.push(`/components/${option.slug}`)

To fix the undefined value issue.

Upvotes: 2

Related Questions