这是indexloc提供的服务,不要输入任何密码
Skip to content

Autosuggest with Algolia and Material UI #783

@Sarath81198

Description

@Sarath81198

I'm using Material UI and Algolia on my React app. I'm trying to implement my customised autocomplete with my customised Search box.

Here's my Search box component

import React, { useState, useEffect } from 'react';
import InputBase from '@material-ui/core/InputBase';
import { fade, makeStyles } from '@material-ui/core/styles';
import IconButton from '@material-ui/core/IconButton'
import Lottie from 'react-lottie';
import searchIcon from './../../assets/animations/SearchIcon.json'
import { useHistory } from "react-router-dom"
import queryString from 'query-string'
import { connectSearchBox } from 'react-instantsearch-dom';

const useStyles = makeStyles((theme) => ({
    search: {
        position: 'relative',
        borderRadius: theme.shape.borderRadius,
        backgroundColor: fade(theme.palette.common.black, 0.15),
        '&:hover': {
            backgroundColor: fade(theme.palette.common.black, 0.25),
        },
        marginLeft: 0,
        marginRight: 20,
        width: '100%',
        [theme.breakpoints.up('sm')]: {
            marginLeft: theme.spacing(1),
            width: 'auto',
        },
    },
    inputRoot: {
        color: 'inherit',
    },
    inputInput: {
        padding: theme.spacing(1, 1, 1, 1),
        // vertical padding + font size from searchIcon
        paddingLeft: `calc(1em + ${theme.spacing(1)}px)`,
        transition: theme.transitions.create('width'),
        width: '100%',
        [theme.breakpoints.up('xs')]: {
            width: '18ch',
            '&:focus': {
                width: '30ch',
            },
        },
    },
}));

function AlgoliaSearchBox({ refine }, {...inputProps}) {
    const classes = useStyles();
    const history = useHistory()
    const [searchIconAnimationIsStopped, setSearchIconAnimationIsStopped] = useState(true)
    const currentPath = window.location.pathname
    const { q } = queryString.parse(window.location.search)
    const [query, setQuery] = useState(q)

    useEffect(() => {
        refine(q)    
    }, [q, refine])

    const searchIconOptions = {
        loop: true,
        autoplay: false,
        animationData: searchIcon,
        rendererSettings: {
            preserveAspectRatio: 'xMidYMid slice'
        }
    };

    const handleQueryOnSubmit = (event) => {
        event.preventDefault()
        const searchQuery = event.target.q.value
        refine(searchQuery)
        history.push(`/items?q=${searchQuery}`)
    }

    if(currentPath !== '/items'){
        return null
    }
    else{
        return (
            <div className={classes.search}>
                <form action="" role="search" 
                    onSubmit={(e) => {
                        e.preventDefault()
                        handleQueryOnSubmit(e)
                        }}>
                    <InputBase
                        name="q"
                        id="q"
                        {...inputProps}
                        
                        classes={{
                            root: classes.inputRoot,
                            input: classes.inputInput,
                        }}
                        inputProps={{ 'aria-label': 'search' }}
                        endAdornment = {
                                <IconButton
                                    color="primary"
                                    type="submit"
                                    onClick={() => {
                                        setSearchIconAnimationIsStopped(false)
                                        setTimeout(() => {
                                            setSearchIconAnimationIsStopped(true)
                                        }, 200);
                                    }}>
                                    <Lottie
                                        options={searchIconOptions}
                                        isStopped={searchIconAnimationIsStopped}
                                        height={20}
                                        width={20}
                                        speed={3}
                                    />
                                </IconButton>
                        }
                    />
                </form>
            </div>
        );
    }
}

const SearchBox = connectSearchBox(AlgoliaSearchBox)

export default SearchBox

And here's my Auto complete component:

import React, { useState} from 'react'
import AutoSuggest from 'react-autosuggest';
import { Highlight, connectAutoComplete } from 'react-instantsearch-dom';
import SearchBox from './SearchBox'

function AutoComplete(props) {
    const { currentRefinement, hits, refine } = props
    const [value, setValue] = useState(currentRefinement)

    const onChange = (event, {newValue}) => {
        setValue(newValue)
    }

    const onSuggestionsFetchRequested = ({ value }) => {
        refine(value)
    }

    const onSuggestionsClearRequested = () => {
        refine()
    }

    const getSuggestionValue = (hit) => {
        return hit.item_name
    }

    const renderSuggestion = (hit) => {
        return <Highlight attribute="item_name" hit={hit} tagName="mark" />
    }

    const inputProps = {
        placeholder: 'Search for a product...',
        onChange: onChange,
        value,
    };

    const renderInputComponent = inputProps => (
            <SearchBox {...inputProps} />
    );

    return (
        <AutoSuggest
            suggestions={hits}
            onSuggestionsFetchRequested={onSuggestionsFetchRequested}
            onSuggestionsClearRequested={onSuggestionsClearRequested}
            getSuggestionValue={getSuggestionValue}
            renderSuggestion={renderSuggestion}
            inputProps={inputProps}
            renderInputComponent={renderInputComponent}
        />
    )
}

export default connectAutoComplete(AutoComplete)

The error I get on console is

index.js:1 Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

Check the render method of `Autowhatever`.
    in ConnectorWrapper (at AutoComplete.js:37)
    in div (created by Autowhatever)
    in Autowhatever (created by Autosuggest)
    in Autosuggest (at AutoComplete.js:41)
    in AutoComplete (created by AlgoliaAutoComplete(AutoComplete))
    in AlgoliaAutoComplete(AutoComplete) (created by Context.Consumer)
    in ConnectorWrapper (at GuestNavbar.js:59)
    in div (at GuestNavbar.js:57)
    in div (created by ForwardRef(Toolbar))
    in ForwardRef(Toolbar) (created by WithStyles(ForwardRef(Toolbar)))
    in WithStyles(ForwardRef(Toolbar)) (at GuestNavbar.js:49)
    in header (created by ForwardRef(Paper))
    in ForwardRef(Paper) (created by WithStyles(ForwardRef(Paper)))
    in WithStyles(ForwardRef(Paper)) (created by ForwardRef(AppBar))
    in ForwardRef(AppBar) (created by WithStyles(ForwardRef(AppBar)))
    in WithStyles(ForwardRef(AppBar)) (at GuestNavbar.js:48)
    in ElevationScroll (at GuestNavbar.js:47)
    in HiddenJs (created by WithWidth(HiddenJs))
    in WithWidth(HiddenJs) (created by Hidden)
    in Hidden (at GuestNavbar.js:46)
    in div (at GuestNavbar.js:44)
    in GuestNavbar (at Navbar.js:10)
    in div (at Navbar.js:9)
    in Navbar (at App.js:119)
    in InstantSearch (at App.js:117)
    in div (at App.js:116)
    in ThemeProvider (at App.js:114)
    in LastLocationProvider (created by Context.Consumer)
    in withRouter(LastLocationProvider) (at App.js:113)
    in MuiPickersUtilsProvider (at App.js:112)
    in Router (created by BrowserRouter)
    in BrowserRouter (at App.js:111)
    in App (at src/index.js:18)
    in StrictMode (at src/index.js:17)
    in Provider (at src/index.js:16)

when I use the one in the example code in the doc

    const renderInputComponent = inputProps => (
        <div>
               <input {...inputProps} />
        </div>
    );

it works fine.

What wrong am I doing? Can someone give me a solution how use renderInputComponent with a customised input component?

TIA

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions