Skip to content

Instantly share code, notes, and snippets.

@mrkaluzny
Created November 4, 2020 17:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrkaluzny/f53a0323621a670e86a51dad7c78b804 to your computer and use it in GitHub Desktop.
Save mrkaluzny/f53a0323621a670e86a51dad7c78b804 to your computer and use it in GitHub Desktop.
Search Component - Gatsby and Flex Search
import React, { Component } from 'react'
import ReactSVG from 'react-svg'
import ResultItem from '@/components/Search/Result'
export default class Search extends Component {
constructor(props) {
super(props)
this.state = {
results: [],
isSearchbarVisible: false,
query: '',
}
this.handleInput = this.handleInput.bind(this)
this.handleClick = this.handleClick.bind(this)
this.handleClickOutside = this.handleClickOutside.bind(this)
}
componentDidMount() {
window.addEventListener('mousedown', this.handleClickOutside)
}
componentWillUnmount() {
window.removeEventListener('mousedown', this.handleClickOutside)
}
handleInput(e) {
let searchInput = e.target.value
if (searchInput.length > 0) {
const results = this.getSearchResults(searchInput)
this.setState({ results: results, query: searchInput })
} else {
this.setState({ results: [], query: searchInput })
}
}
handleClick() {
this.setState(
(state) => {
return {
isSearchbarVisible: !state.isSearchbarVisible,
}
},
() => {
this.searchInput.focus()
},
)
}
handleClickOutside(e) {
if (!this.node.contains(e.target)) {
this.setState({
isSearchbarVisible: false,
query: '',
results: [],
})
}
}
getSearchResults(query) {
var index = window.__FLEXSEARCH__.en.index
var store = window.__FLEXSEARCH__.en.store
if (!query || !index) {
return []
} else {
var results = []
Object.keys(index).forEach((idx) => {
results.push(...index[idx].values.search(query))
})
results = Array.from(new Set(results))
var nodes = store
.filter((node) => (results.includes(node.id) ? node : null))
.map((node) => node.node)
return nodes
}
}
render() {
return (
<div className='Search' ref={(node) => (this.node = node)}>
<button className='Search__button' onClick={this.handleClick}>
<ReactSVG src='/img/search.svg'></ReactSVG>
<span className='sr-only'>Search</span>
</button>
<div
className={`Search__input ${
this.state.isSearchbarVisible ? '' : 'Search__input--hidden'
}`}>
<input
type='text'
className='search-input'
data-aos='fade-left'
placeholder='Search..'
value={this.state.query}
onChange={this.handleInput}
ref={(input) => (this.searchInput = input)}
/>
<div className='Search__results'>
{this.state.results.map(
(page) =>
page.layout !== 'hidden' &&
page.layout !== 'null' && (
<ResultItem page={page} key={page.id}></ResultItem>
),
)}
</div>
</div>
</div>
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment