Search code examples
reactjscomponentsmaterial-uijsxalgolia

How to connect Algolia and @material-ui


This is the documentation of how to create a basic SearchBox element from just an input field in Algolia. The problem is, Algolia's ends up looking pretty ugly

That's where material-ui comes in. I have used AppBar before which contains a search element, so my thinking was to instantiate SearchBox within my AppBar.js component, but with material-ui's proprietary InputBase (instead of boring html input).

I'll paste the code I have so far below but it's refusing to compile with InputBase (and more specifically it's associated props) being used to create a custom SearchBox element.

If anyone has any experience with meshing different API's like this or think you might know what's going on, don't hesitate to let me know!

import React from 'react';
import PropTypes from 'prop-types';
import AppBar from '@material-ui/core/Appbar';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import InputBase from '@material-ui/core/InputBase';
import {fade} from '@material-ui/core/styles/colorManipulator';
import {withStyles} from "@material-ui/core/styles";
import SearchIcon from '@material-ui/icons/Search';
import { connectSearchBox } from 'react-instantsearch-dom';

const styles = theme => ({
    root:{
        width: '100%',
    },
    grow:{
        flexGrow: 1,
    },
    menuButton:{
        marginLeft: -12,
        marginRight: 20,
    },
    title:{
        display: 'none',
        [theme.breakpoints.up('sm')]:{
            display: 'block',
        },
    },
    search:{
        position: 'relative',
        borderRadius: theme.shape.borderRadius,
        backgroundColor: fade(theme.palette.common.white, 0.15),
        '&:hover':{
            backgroundColor: fade(theme.palette.common.white, 0.25),
        },
        marginLeft: 0,
        width: '100%',
        [theme.breakpoints.up('sm')]:{
            marginLeft: theme.spacing.unit,
            width: 'auto',
        },
    },
    searchIcon:{
        width: theme.spacing.unit * 9,
        height: '100%',
        position: 'absolute',
        pointerEvents: 'none',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
    },
    inputRoot:{
        color: 'inherit',
        width: '100%',
    },
    inputInput:{
        paddingTop: theme.spacing.unit,
        paddingRight: theme.spacing.unit,
        paddingBottom: theme.spacing.unit,
        paddingLeft: theme.spacing.unit * 10,
        transition: theme.transitions.create('width'),
        width: '100%',
        [theme.breakpoints.up('sm')]:{
            width: 120,
            '&:focus':{
                width: 200,
            },
        },
    },
});

function SearchBox({currentRefinement, refine}, props){
    const {classes} = props;
    return(
        <InputBase
            type='search'
            value={currentRefinement}
            onChange={event => refine(event.currentTarget.value)}
            placeholder="Search for Destination by Name, State, and keywords..."
            classes={{
                root: classes.inputRoot,
                input: classes.inputInput,
            }}
        />
    );
}


const CustomSearchBox = connectSearchBox(SearchBox);

function SearchAppBar(props){
    const {classes} = props;
    return(
        <div className={classes.root}>
            <AppBar position="static">
                <Toolbar>
                    <Typography className={classes.title} variant="h6" color='inherit' noWrap>
                    title
                    </Typography>
                    <div className={classes.grow}/>
                    <div className={classes.search}>
                        <div className={classes.searchIcon}>
                            <SearchIcon/>
                        </div>
                        <CustomSearchBox/>
                    </div>
                </Toolbar>
            </AppBar>
        </div>
    );
}

SearchAppBar.propTypes = {
    classes: PropTypes.object.isRequired,
};

export default withStyles(styles)(SearchAppBar);

(as you can probably tell, I have gone very by the book with respect to documentation - I haven't tried anything special)

enter image description here


Solution

  • If you want to use the material ui search box component instead of Algolia's, you can use connectSearchBox(); to sync the material ui search box and Algolia search box API.

    import { InstantSearch, connectSearchBox } from "react-instantsearch-dom";
    const CustomSearchBox = connectSearchBox(MaterialUISearchBox);
    

    Inside MaterialUISearchBox component, you will use the props Algolia provides: currentRefinement and refine().

            <InputBase
              placeholder="Search…"
              inputProps={{ "aria-label": "search" }}
              value={this.props.currentRefinement}
              onChange={(e) => this.props.refine(this.currentTarget.value)}
              searchAsYouType={false}
            />
    

    Please check the url for further details about Algolia's custom components.

    https://www.algolia.com/doc/api-reference/widgets/search-box/react/