Created
December 30, 2019 14:36
-
-
Save g33kChris/dbf39fcc5721ff47c57cc725a4ffa21d to your computer and use it in GitHub Desktop.
Example Tag related search code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Wrap the application in the InstantSearch provider so the search context is available within the application component tree | |
<InstantSearchProvider> | |
{element} | |
</InstantSearchProvider> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export interface ApplicationState { | |
searchQuery: string; | |
searchFocus: boolean; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from "react" | |
import { Highlight, Snippet } from "react-instantsearch-dom" | |
import { Link } from "gatsby" | |
import { Root, Item } from './hit-components-styles'; | |
export const PageHit = clickHandler => ({ hit }) => ( | |
<div> | |
<Link to={hit.slug} onClick={clickHandler}> | |
<h4> | |
<Highlight attribute="title" hit={hit} tagName="mark" /> | |
</h4> | |
</Link> | |
<Snippet attribute="excerpt" hit={hit} tagName="mark" /> | |
</div> | |
) | |
export const PostHit = clickHandler => ({ hit }) => ( | |
<Root> | |
<Link to={`/blog/` + hit.slug} onClick={clickHandler}> | |
<Item> | |
<Highlight attribute="title" hit={hit} tagName="mark" /> | |
</Item> | |
</Link> | |
</Root> | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { ApplicationState } from './application-state.interface'; | |
export const initialState: ApplicationState = { | |
searchQuery: '', | |
searchFocus: false | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
interface InstantSearchProviderProps { | |
state: ApplicationState; | |
dispatch: ({ type }: { type: string; payload?: any; }) => void; | |
children: any | |
} | |
function useOnClickOutside(ref, handler) { | |
React.useEffect( | |
() => { | |
const listener = event => { | |
// Do nothing if clicking ref's element or descendent elements | |
if (!ref.current || ref.current.contains(event.target)) { | |
return; | |
} | |
handler(event); | |
}; | |
document.addEventListener('mousedown', listener); | |
document.addEventListener('touchstart', listener); | |
return () => { | |
document.removeEventListener('mousedown', listener); | |
document.removeEventListener('touchstart', listener); | |
}; | |
}, | |
[ref, handler] | |
); | |
} | |
function InstantSearchProvider(props: InstantSearchProviderProps) { | |
const ref = React.createRef(); | |
const searchClient = React.useMemo( | |
() => | |
algoliasearch( | |
process.env.GATSBY_ALGOLIA_APP_ID, | |
process.env.GATSBY_ALGOLIA_SEARCH_KEY | |
), | |
[] | |
) | |
useOnClickOutside(ref, () => props.dispatch({ type: searchFocusActionTypes.SET_FOCUS, payload: false })) | |
return ( | |
<> | |
<InstantSearch | |
searchClient={searchClient} | |
indexName={searchIndices[0].name} | |
onSearchStateChange={({ query }) => props.dispatch({ type: searchActionTypes.SET_QUERY, payload: query })} | |
root={{ Root, props: { ref } }} | |
> | |
{ props.children } | |
</InstantSearch> | |
</> | |
) | |
} | |
export default withApplicationState(InstantSearchProvider) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { ApplicationState } from './application-state.interface'; | |
import { StateAction } from './state-action.interface'; | |
import searchFocusReducer from './reducers/searchFocus.reducer'; | |
import searchReducer from './reducers/search.reducer'; | |
export default function rootReducer(state: ApplicationState, action: StateAction): ApplicationState { | |
const { searchQuery, searchFocus } = state; | |
return { | |
searchQuery: searchReducer(searchQuery, action), | |
searchFocus: searchFocusReducer(searchFocus, action) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { StateAction } from '../state-action.interface'; | |
export const searchFocusActionTypes = { | |
SET_FOCUS: 'SET_FOCUS' | |
} | |
export default function searchFocusReducer(state: boolean = false, action: StateAction): boolean { | |
switch(action.type) { | |
case searchFocusActionTypes.SET_FOCUS: { | |
return action.payload; | |
} | |
default: | |
return state; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export const searchIndices = [ | |
{ name: `Posts`, title: `Blog Posts`, hitComp: `PostHit` } | |
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { StateAction } from '../state-action.interface'; | |
export const searchActionTypes = { | |
SET_QUERY: 'SET_QUERY' | |
} | |
export default function searchReducer(state: string = '', action: StateAction): string { | |
switch(action.type) { | |
case searchActionTypes.SET_QUERY: { | |
return action.payload; | |
} | |
default: | |
return state; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from "react"; | |
import { | |
Index, | |
connectStateResults | |
} from "react-instantsearch-dom"; | |
import { | |
HitsWrapper, | |
PoweredBy, | |
ResultsHeader, | |
StatText, | |
IndicieHeader, | |
StyledHits as Hits, | |
SearchControl, | |
SearchInput, | |
CancelButton | |
} from "./search-styles"; | |
import Input from "../input"; | |
import * as hitComponents from "../hit-components"; | |
import { searchIndices } from '../../../providers/search-indices.const'; | |
import { ApplicationState } from "../../../providers/application-state.interface"; | |
import { searchFocusActionTypes } from '../../../providers/reducers/searchFocus.reducer'; | |
import withApplicationState from "../../_hocs/with-application-state"; | |
const Results = connectStateResults( | |
({ searchState: state, searchResults: res, children }) => | |
res && res.nbHits > 0 ? children : <StatText>{ `No results for '${state.query}'`}</StatText> | |
) | |
const Stats = connectStateResults( | |
({ searchResults: res }) => | |
res && res.nbHits > 0 && `${res.nbHits} result${res.nbHits > 1 ? `s` : ``}` | |
) | |
interface SearchProps { | |
collapse: any; | |
hitsAsGrid: any; | |
cancelSearch: any; | |
state: ApplicationState; | |
dispatch: ({ type }: { type: string; payload?: any; }) => void; | |
} | |
const Search = (props: SearchProps) => { | |
const { collapse, hitsAsGrid, cancelSearch, state, dispatch } = props; | |
return( | |
<> | |
<SearchControl> | |
<SearchInput> | |
<Input | |
onFocus={() => dispatch({ type: searchFocusActionTypes.SET_FOCUS, payload: true })} | |
{...{ collapse, focus: state.searchFocus }} | |
/> | |
</SearchInput> | |
<CancelButton onClick={() => cancelSearch()}>Cancel</CancelButton> | |
</SearchControl> | |
<HitsWrapper show={state.searchQuery.length > 0 } asGrid={hitsAsGrid}> | |
{ searchIndices.map(({ name, title, hitComp }) => ( | |
<Index key={name} indexName={name}> | |
<IndicieHeader> | |
<ResultsHeader>{title}</ResultsHeader> | |
<StatText><Stats /></StatText> | |
</IndicieHeader> | |
<Results> | |
<Hits hitComponent={hitComponents[hitComp](() => dispatch({ type: searchFocusActionTypes.SET_FOCUS, payload: false }))} /> | |
</Results> | |
</Index> | |
))} | |
<PoweredBy /> | |
</HitsWrapper> | |
</> | |
); | |
}; | |
export default withApplicationState(Search); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
interface StateProviderProps { | |
children: any; | |
} | |
interface IStateContext { | |
state: ApplicationState; | |
dispatch: ({type}:{type:string}) => void; | |
} | |
export const GlobalStore = React.createContext({} as IStateContext); | |
const asyncer = (dispatch: any, state: ApplicationState) => (action: any) => | |
typeof action === 'function' ? action(dispatch, state) : dispatch(action); | |
export function StateProvider(props: StateProviderProps) { | |
const [state, dispatchBase] = React.useReducer(rootReducer, initialState); | |
const dispatch = React.useCallback(asyncer(dispatchBase, state), []) | |
return ( | |
<GlobalStore.Provider value={{ state, dispatch }}> | |
{ props.children } | |
</GlobalStore.Provider> | |
) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { GlobalStore } from '../../providers/state.provider'; | |
export default function withApplicationState(Component: any) { | |
return function WrapperComponent(props: any) { | |
return ( | |
<GlobalStore.Consumer> | |
{context => <Component {...props} state={context.state} dispatch={context.dispatch} />} | |
</GlobalStore.Consumer> | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment