From e0b5013d3900ab4d31bbeb88938170437aa3c194 Mon Sep 17 00:00:00 2001 From: Cindy <74145775+ElemelonWind@users.noreply.github.com> Date: Thu, 14 Jul 2022 16:17:54 -0400 Subject: [PATCH 1/5] Answers -> Search 1: Customer facing renaming (#141) * Update README.md * README and package updates * prelim renaming * Deprecation tag and exports updates * public deprecation message * Deprecation fix * Update index.ts * Delete deprecation.test.tsx * deprecated file * fix lint issues * more updates * test fixes * readme fix * fix types exports --- README.md | 88 +++++++++---------- package-lock.json | 4 +- package.json | 6 +- ...essContext.ts => SearchHeadlessContext.ts} | 2 +- ...rovider.tsx => SearchHeadlessProvider.tsx} | 10 +-- src/deprecated.ts | 51 +++++++++++ src/index.ts | 27 +++--- src/subscribeToStateUpdates.tsx | 14 +-- src/useAnswersActions.ts | 14 --- src/useAnswersUtilities.ts | 9 -- src/useSearchActions.ts | 14 +++ ...useAnswersState.tsx => useSearchState.tsx} | 22 ++--- src/useSearchUtilities.ts | 9 ++ ...st.tsx => SearchHeadlessProvider.test.tsx} | 4 +- tests/useAnswersActions.test.tsx | 16 ---- tests/useSearchActions.test.tsx | 16 ++++ ...State.test.tsx => useSearchState.test.tsx} | 46 +++++----- tsconfig.base.json | 2 +- 18 files changed, 203 insertions(+), 151 deletions(-) rename src/{AnswersHeadlessContext.ts => SearchHeadlessContext.ts} (64%) rename src/{AnswersHeadlessProvider.tsx => SearchHeadlessProvider.tsx} (78%) create mode 100644 src/deprecated.ts delete mode 100644 src/useAnswersActions.ts delete mode 100644 src/useAnswersUtilities.ts create mode 100644 src/useSearchActions.ts rename src/{useAnswersState.tsx => useSearchState.tsx} (61%) create mode 100644 src/useSearchUtilities.ts rename tests/{AnswersHeadlessProvider.test.tsx => SearchHeadlessProvider.test.tsx} (84%) delete mode 100644 tests/useAnswersActions.test.tsx create mode 100644 tests/useSearchActions.test.tsx rename tests/{useAnswersState.test.tsx => useSearchState.test.tsx} (82%) diff --git a/README.md b/README.md index a17a7107..52b1e4fb 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,18 @@ -# Answers Headless React +# Search Headless React -Answers Headless React is the official React UI Bindings layer for [Answers Headless](https://www.npmjs.com/package/@yext/answers-headless). +Search Headless React is the official React UI Bindings layer for [Search Headless](https://www.npmjs.com/package/@yext/search-headless). Written in 100% TypeScript.
- - NPM version + + NPM version License - - Coverage Status + + Coverage Status

@@ -20,95 +20,95 @@ Written in 100% TypeScript. ## Installation ```shell -npm install @yext/answers-headless-react +npm install @yext/search-headless-react ``` -## Getting Started - `AnswersHeadlessProvider` +## Getting Started - `SearchHeadlessProvider` -Answers Headless React includes an `` component, which instantiates an AnswersHeadless instance and makes it available to the rest of your app. +Search Headless React includes an `` component, which instantiates an SearchHeadless instance and makes it available to the rest of your app. ```tsx -import { AnswersHeadlessProvider } from '@yext/answers-headless-react'; +import { SearchHeadlessProvider } from '@yext/search-headless-react'; import SearchBar from './SearchBar'; import MostRecentSearch from './MostRecentSearch'; import UniversalResults from './UniversalResults'; function MyApp() { return ( - - {/* Add components that use Answers as children */} + {/* Add components that use Search as children */} - + ); } ``` -## Respond to State Updates with `useAnswersState` +## Respond to State Updates with `useSearchState` -`useAnswersState` reads a value from the `AnswersHeadless` state and subscribes to updates. +`useSearchState` reads a value from the `SearchHeadless` state and subscribes to updates. ```tsx -import { useAnswersState } from '@yext/answers-headless-react'; +import { useSearchState } from '@yext/search-headless-react'; -export default function MostRecentSearch() { - const mostRecentSearch = useAnswersState(state => state.query.mostRecentSearch); + default function MostRecentSearch() { + const mostRecentSearch = useSearchState(state => state.query.mostRecentSearch); return
Showing results for {mostRecentSearch}
; } ``` -## Dispatch Actions with `useAnswersActions` +## Dispatch Actions with `useSearchActions` -`useAnswersActions` allows you to dispatch actions using the `AnswersHeadless` instance. +`useSearchActions` allows you to dispatch actions using the `SearchHeadless` instance. These include performing searches, getting autocomplete suggestions, and adding filters. -For a full list of capabilities see [the answers-headless docs](https://www.npmjs.com/package/@yext/answers-headless). +For a full list of capabilities see [the search-headless docs](https://www.npmjs.com/package/@yext/search-headless). ```tsx -import { useAnswersActions } from '@yext/answers-headless-react'; +import { useSearchActions } from '@yext/search-headless-react'; import { ChangeEvent, KeyboardEvent, useCallback } from 'react'; function SearchBar() { - const answers = useAnswersActions(); + const search = useSearchActions(); const handleTyping = useCallback((e: ChangeEvent) => { - answers.setQuery(e.target.value); - }, [answers]); + search.setQuery(e.target.value); + }, [search]); const handleKeyDown = useCallback((evt: KeyboardEvent) => { if (evt.key === 'Enter' ) { - answers.executeUniversalQuery(); + search.executeUniversalQuery(); } - }, [answers]); + }, [search]); return ; } ``` -## `AnswersHeadlessContext` -### Class Components +## `SearchHeadlessContext` +## Class Components -For users that want to use class components instead of functional components, you can use the `AnswersHeadlessContext` directly to dispatch actions and receive updates from state. +For users that want to use class components instead of functional components, you can use the `SearchHeadlessContext` directly to dispatch actions, and the `subscribeToStateUpdates` HOC to receive updates from state. -As an example, here is our simple SearchBar again, rewritten as a class using `AnswersHeadlessContext`. +As an example, here is our simple SearchBar again, rewritten as a class using `SearchHeadlessContext`. ```tsx -import { AnswersHeadlessContext, AnswersHeadless, State } from '@yext/answers-headless-react'; +import { SearchHeadlessContext, SearchHeadless, State } from '@yext/search-headless-react'; import { Component } from 'react'; export default class Searcher extends Component { - static contextType = AnswersHeadlessContext; + static contextType = SearchHeadlessContext; unsubscribeQueryListener: any; state = { query: "" }; componentDidMount() { - const answers: AnswersHeadless = this.context; - this.unsubscribeQueryListener = answers.addListener({ + const search: SearchHeadless = this.context; + this.unsubscribeQueryListener = search.addListener({ valueAccessor: (state: State) => state.query.mostRecentSearch, callback: newPropsFromState => { this.setState({ query: newPropsFromState }) @@ -121,15 +121,15 @@ export default class Searcher extends Component { } render() { - const answers: AnswersHeadless = this.context; + const search: SearchHeadless = this.context; return (

Query: {this.state.query}

answers.setQuery(evt.target.value)} + onChange={evt => search.setQuery(evt.target.value)} onKeyDown={evt => { if (evt.key === 'Enter') { - answers.executeUniversalQuery(); + search.executeUniversalQuery(); } }} /> @@ -139,14 +139,14 @@ export default class Searcher extends Component { } ``` -## `useAnswersUtilities` +## `useSearchUtilities` -We offer a `useAnswersUtilities` convenience hook for accessing `AnswersHeadless.utilities`, which offers a number of stateless utility methods. -The `answersUtilities` and `answersUtilitiesFromActions` variables below are equivalent. +We offer a `useSearchUtilities` convenience hook for accessing `SearchHeadless.utilities`, which offers a number of stateless utility methods. +The `searchUtilities` and `searchUtilitiesFromActions` variables below are equivalent. -For class components, you can access `AnswersUtilities` through `AnswersHeadlessContext`. +For class components, you can access `SearchUtilities` through `SearchHeadlessContext`. ```ts -const answersUtilities = useAnswersUtilities(); -const answersUtilitiesFromActions = useAnswersActions().utilities; +const searchUtilities = useSearchUtilities(); +const searchUtilitiesFromActions = useSearchActions().utilities; ``` diff --git a/package-lock.json b/package-lock.json index b43f4106..dba47ef4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "@yext/answers-headless-react", + "name": "@yext/search-headless-react", "version": "1.2.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "@yext/answers-headless-react", + "name": "@yext/search-headless-react", "version": "1.2.0", "license": "BSD-3-Clause", "dependencies": { diff --git a/package.json b/package.json index cf273a74..3beaffa6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "@yext/answers-headless-react", + "name": "@yext/search-headless-react", "version": "1.2.0", - "description": "The official React UI Bindings layer for Answers Headless", + "description": "The official React UI Bindings layer for Search Headless", "main": "./lib/esm/src/index.js", "license": "BSD-3-Clause", "types": "./lib/esm/src/index.d.ts", @@ -106,6 +106,6 @@ }, "repository": { "type": "git", - "url": "https://github.com/yext/answers-headless-react.git" + "url": "https://github.com/yext/search-headless-react.git" } } diff --git a/src/AnswersHeadlessContext.ts b/src/SearchHeadlessContext.ts similarity index 64% rename from src/AnswersHeadlessContext.ts rename to src/SearchHeadlessContext.ts index c2d3504d..bb3a7e6d 100644 --- a/src/AnswersHeadlessContext.ts +++ b/src/SearchHeadlessContext.ts @@ -2,4 +2,4 @@ import { AnswersHeadless } from '@yext/answers-headless'; import { createContext } from 'react'; // The default is empty because we don't know the user's config yet -export const AnswersHeadlessContext = createContext({} as AnswersHeadless); +export const SearchHeadlessContext = createContext({} as AnswersHeadless); \ No newline at end of file diff --git a/src/AnswersHeadlessProvider.tsx b/src/SearchHeadlessProvider.tsx similarity index 78% rename from src/AnswersHeadlessProvider.tsx rename to src/SearchHeadlessProvider.tsx index 1a33d740..d805f73e 100644 --- a/src/AnswersHeadlessProvider.tsx +++ b/src/SearchHeadlessProvider.tsx @@ -1,6 +1,6 @@ import { PropsWithChildren } from 'react'; import { provideAnswersHeadless, AnswersHeadless, HeadlessConfig } from '@yext/answers-headless'; -import { AnswersHeadlessContext } from './AnswersHeadlessContext'; +import { SearchHeadlessContext } from './SearchHeadlessContext'; import acquireSessionId from './utils/acquireSessionId'; import packageJson from '../package.json'; @@ -11,7 +11,7 @@ type Props = HeadlessConfig & { sessionTrackingEnabled?: boolean }; -export function AnswersHeadlessProvider(props: PropsWithChildren): JSX.Element { +export function SearchHeadlessProvider(props: PropsWithChildren): JSX.Element { const { children, verticalKey, sessionTrackingEnabled=true, ...answersConfig } = props; const additionalHttpHeaders = { 'Client-SDK': { @@ -27,8 +27,8 @@ export function AnswersHeadlessProvider(props: PropsWithChildren): JSX.El sessionId && answers.setSessionId(sessionId); } return ( - + {children} - + ); -} +} \ No newline at end of file diff --git a/src/deprecated.ts b/src/deprecated.ts new file mode 100644 index 00000000..bcacf2e3 --- /dev/null +++ b/src/deprecated.ts @@ -0,0 +1,51 @@ +import { useSearchActions, SearchActions } from './useSearchActions'; +import { StateSelector, useSearchState } from './useSearchState'; +import { useSearchUtilities, SearchUtilities } from './useSearchUtilities'; +import { SearchHeadlessProvider } from './SearchHeadlessProvider'; +import { SearchHeadlessContext } from './SearchHeadlessContext'; +import { PropsWithChildren } from 'react'; +import { HeadlessConfig } from '@yext/answers-headless'; + +type Props = HeadlessConfig & { + verticalKey?: string, + sessionTrackingEnabled?: boolean +}; + +/** + * @deprecated AnswersHeadlessContext has been deprecated and replaced by SearchHeadlessContext + */ +export const AnswersHeadlessContext = SearchHeadlessContext; + +/** + * @deprecated AnswersActions has been deprecated and replaced by SearchActions + */ +export type AnswersActions = SearchActions; + +/** + * @deprecated AnswersUtilities has been deprecated and replaced by SearchUtilities + */ +export type AnswersUtilities = SearchUtilities; + +/** + * @deprecated useAnswersActions has been deprecated and replaced by useSearchActions + */ +export function useAnswersActions(): SearchActions { return useSearchActions(); } + +/** + * @deprecated useAnswersState has been deprecated and replaced by useSearchState + */ +export function useAnswersState(stateSelector: StateSelector): T { + return useSearchState(stateSelector); +} + +/** + * @deprecated useAnswersUtilities has been deprecated and repalced by useSearchUtilities + */ +export function useAnswersUtilities(): SearchUtilities { return useSearchUtilities(); } + +/** + * @deprecated AnswersHeadlessProvider has been deprecated and replaced by SearfchHeadlessProvider + */ +export function AnswersHeadlessProvider(props: PropsWithChildren): JSX.Element { + return SearchHeadlessProvider(props); +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index c7e32c3a..040eee4e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,19 +1,20 @@ -import { useAnswersActions, AnswersActions } from './useAnswersActions'; -import { useAnswersState, StateSelector } from './useAnswersState'; -import { useAnswersUtilities, AnswersUtilities } from './useAnswersUtilities'; +import { useSearchActions, SearchActions } from './useSearchActions'; +import { useSearchState, StateSelector } from './useSearchState'; +import { useSearchUtilities, SearchUtilities } from './useSearchUtilities'; import { subscribeToStateUpdates } from './subscribeToStateUpdates'; -import { AnswersHeadlessProvider } from './AnswersHeadlessProvider'; -import { AnswersHeadlessContext } from './AnswersHeadlessContext'; +import { SearchHeadlessProvider } from './SearchHeadlessProvider'; +import { SearchHeadlessContext } from './SearchHeadlessContext'; export * from '@yext/answers-headless'; +export * from './deprecated'; export { - AnswersHeadlessContext, + SearchHeadlessContext, subscribeToStateUpdates, - useAnswersActions, - useAnswersState, - useAnswersUtilities, - AnswersHeadlessProvider, - AnswersActions, - AnswersUtilities, + useSearchActions, + useSearchState, + useSearchUtilities, + SearchHeadlessProvider, + SearchActions, + SearchUtilities, StateSelector -}; +}; \ No newline at end of file diff --git a/src/subscribeToStateUpdates.tsx b/src/subscribeToStateUpdates.tsx index e4c86dc9..7cebd1f0 100644 --- a/src/subscribeToStateUpdates.tsx +++ b/src/subscribeToStateUpdates.tsx @@ -1,18 +1,18 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { ComponentType, useReducer, useEffect, useContext } from 'react'; import { State } from '@yext/answers-headless'; -import { AnswersHeadlessContext } from './AnswersHeadlessContext'; +import { SearchHeadlessContext } from './SearchHeadlessContext'; import isShallowEqual from './utils/isShallowEqual'; type SubscriberGenerator = (WrappedComponent: ComponentType) => (props: any) => JSX.Element; /** * Generates a HOC that updates a given Component's props based on the current - * answers-headless state and a given mapping function. + * search-headless state and a given mapping function. * * @deprecated - * For class component, use `AnswersHeadlessContext` directly to dispatch actions and receive state updates. - * For functional component, use `useAnswersActions` and `useAnswersState` instead. + * For class component, use `SearchHeadlessContext` directly to dispatch actions and receive state updates. + * For functional component, use `useSearchActions` and `useSearchState` instead. */ export function subscribeToStateUpdates( mapStateToProps: (s: State) => Record @@ -20,13 +20,13 @@ export function subscribeToStateUpdates( const generateSubscriberHOC: SubscriberGenerator = WrappedComponent => { /** * Keep manual track of the props mapped from state instead of storing - * it in the AnswersHeadlessSubscriber's state. This avoids react's batching + * it in the SearchHeadlessSubscriber's state. This avoids react's batching * of state updates, which can result in mappedState not updating immediately. - * This can, in turn, result in extra answers-headless listener invocations. + * This can, in turn, result in extra search-headless listener invocations. */ let previousPropsFromState = {}; return function AnswersHeadlessSubscriber(props: Record) { - const answers = useContext(AnswersHeadlessContext); + const answers = useContext(SearchHeadlessContext); const [mergedProps, dispatch] = useReducer(() => { return { ...props, diff --git a/src/useAnswersActions.ts b/src/useAnswersActions.ts deleted file mode 100644 index 3283dbe5..00000000 --- a/src/useAnswersActions.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { AnswersHeadless } from '@yext/answers-headless'; -import { useContext } from 'react'; -import { AnswersHeadlessContext } from './AnswersHeadlessContext'; - -export type AnswersActions = AnswersHeadless; - -export function useAnswersActions(): AnswersActions { - const answersHeadless = useContext(AnswersHeadlessContext); - if (answersHeadless.state === undefined) { - throw new Error('Attempted to call useAnswersActions() outside of AnswersHeadlessProvider.' - + ' Please ensure that \'useAnswersActions()\' is called within an AnswersHeadlessProvider component.'); - } - return answersHeadless; -} \ No newline at end of file diff --git a/src/useAnswersUtilities.ts b/src/useAnswersUtilities.ts deleted file mode 100644 index f1a77f5b..00000000 --- a/src/useAnswersUtilities.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { AnswersHeadless } from '@yext/answers-headless'; -import { useContext } from 'react'; -import { AnswersHeadlessContext } from './AnswersHeadlessContext'; - -export type AnswersUtilities = AnswersHeadless['utilities']; - -export function useAnswersUtilities(): AnswersUtilities { - return useContext(AnswersHeadlessContext).utilities; -} \ No newline at end of file diff --git a/src/useSearchActions.ts b/src/useSearchActions.ts new file mode 100644 index 00000000..746d2b34 --- /dev/null +++ b/src/useSearchActions.ts @@ -0,0 +1,14 @@ +import { AnswersHeadless } from '@yext/answers-headless'; +import { useContext } from 'react'; +import { SearchHeadlessContext } from './SearchHeadlessContext'; + +export type SearchActions = AnswersHeadless; + +export function useSearchActions(): SearchActions { + const answersHeadless = useContext(SearchHeadlessContext); + if (answersHeadless.state === undefined) { + throw new Error('Attempted to call useSearchActions() outside of SearchHeadlessProvider.' + + ' Please ensure that \'useSearchActions()\' is called within an SearchHeadlessProvider component.'); + } + return answersHeadless; +} \ No newline at end of file diff --git a/src/useAnswersState.tsx b/src/useSearchState.tsx similarity index 61% rename from src/useAnswersState.tsx rename to src/useSearchState.tsx index 05678541..9615368d 100644 --- a/src/useAnswersState.tsx +++ b/src/useSearchState.tsx @@ -1,24 +1,24 @@ import { useCallback, useContext, useEffect, useRef } from 'react'; import { State } from '@yext/answers-headless'; -import { AnswersHeadlessContext } from './AnswersHeadlessContext'; +import { SearchHeadlessContext } from './SearchHeadlessContext'; import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/shim/with-selector'; export type StateSelector = (s: State) => T; /** - * Returns the Answers State returned by the map function. + * Returns the Search State returned by the map function. * Uses "use-sync-external-store/shim" to handle reading * and subscribing from external store in React version * pre-18 and 18. */ -export function useAnswersState(stateSelector: StateSelector): T { - const answers = useContext(AnswersHeadlessContext); - if (answers.state === undefined) { - throw new Error('Attempted to call useAnswersState() outside of AnswersHeadlessProvider.' - + ' Please ensure that \'useAnswersState()\' is called within an AnswersHeadlessProvider component.'); +export function useSearchState(stateSelector: StateSelector): T { + const search = useContext(SearchHeadlessContext); + if (search.state === undefined) { + throw new Error('Attempted to call useSearchState() outside of SearchHeadlessProvider.' + + ' Please ensure that \'useSearchState()\' is called within an SearchHeadlessProvider component.'); } - const getSnapshot = useCallback(() => answers.state, [answers.state]); + const getSnapshot = useCallback(() => search.state, [search.state]); const isMountedRef = useRef(false); useEffect(() => { isMountedRef.current = true; @@ -28,7 +28,7 @@ export function useAnswersState(stateSelector: StateSelector): T { }, []); const subscribe = useCallback(cb => - answers.addListener({ + search.addListener({ valueAccessor: state => state, callback: () => { // prevent React state update on an unmounted component @@ -37,7 +37,7 @@ export function useAnswersState(stateSelector: StateSelector): T { } cb(); } - }), [answers]); + }), [search]); const selectedState = useSyncExternalStoreWithSelector( subscribe, @@ -46,4 +46,4 @@ export function useAnswersState(stateSelector: StateSelector): T { stateSelector ); return selectedState; -} +} \ No newline at end of file diff --git a/src/useSearchUtilities.ts b/src/useSearchUtilities.ts new file mode 100644 index 00000000..1cc4cb8a --- /dev/null +++ b/src/useSearchUtilities.ts @@ -0,0 +1,9 @@ +import { AnswersHeadless } from '@yext/answers-headless'; +import { useContext } from 'react'; +import { SearchHeadlessContext } from './SearchHeadlessContext'; + +export type SearchUtilities = AnswersHeadless['utilities']; + +export function useSearchUtilities(): SearchUtilities { + return useContext(SearchHeadlessContext).utilities; +} \ No newline at end of file diff --git a/tests/AnswersHeadlessProvider.test.tsx b/tests/SearchHeadlessProvider.test.tsx similarity index 84% rename from tests/AnswersHeadlessProvider.test.tsx rename to tests/SearchHeadlessProvider.test.tsx index 56cd9070..bd5c5040 100644 --- a/tests/AnswersHeadlessProvider.test.tsx +++ b/tests/SearchHeadlessProvider.test.tsx @@ -1,4 +1,4 @@ -import { AnswersHeadlessProvider, SandboxEndpoints } from '../src'; +import { SearchHeadlessProvider, SandboxEndpoints } from '../src'; import { render } from '@testing-library/react'; import { provideAnswersHeadless } from '@yext/answers-headless'; @@ -17,7 +17,7 @@ it('correctly passes through an answers config with sandbox endpoints', () => { endpoints: SandboxEndpoints }; - render(); + render(); expect(provideAnswersHeadless).toHaveBeenCalledTimes(1); expect(provideAnswersHeadless).toHaveBeenCalledWith(config, expect.anything()); }); \ No newline at end of file diff --git a/tests/useAnswersActions.test.tsx b/tests/useAnswersActions.test.tsx deleted file mode 100644 index 87b0ee37..00000000 --- a/tests/useAnswersActions.test.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { useAnswersActions } from '../src'; -import { render } from '@testing-library/react'; - -it('invoke useAnswersActions outside of AnswersHeadlessProvider', () => { - function Test(): JSX.Element { - const answersActions = useAnswersActions(); - answersActions.setQuery(''); - return
Test
; - } - jest.spyOn(global.console, 'error').mockImplementation(); - const expectedError = new Error( - 'Attempted to call useAnswersActions() outside of AnswersHeadlessProvider.' + - ' Please ensure that \'useAnswersActions()\' is called within an AnswersHeadlessProvider component.'); - expect(() => render()).toThrow(expectedError); - jest.clearAllMocks(); -}); \ No newline at end of file diff --git a/tests/useSearchActions.test.tsx b/tests/useSearchActions.test.tsx new file mode 100644 index 00000000..bc5b604d --- /dev/null +++ b/tests/useSearchActions.test.tsx @@ -0,0 +1,16 @@ +import { useSearchActions } from '../src'; +import { render } from '@testing-library/react'; + +it('invoke useSearchActions outside of SearchHeadlessProvider', () => { + function Test(): JSX.Element { + const searchActions = useSearchActions(); + searchActions.setQuery(''); + return
Test
; + } + jest.spyOn(global.console, 'error').mockImplementation(); + const expectedError = new Error( + 'Attempted to call useSearchActions() outside of SearchHeadlessProvider.' + + ' Please ensure that \'useSearchActions()\' is called within an SearchHeadlessProvider component.'); + expect(() => render()).toThrow(expectedError); + jest.clearAllMocks(); +}); \ No newline at end of file diff --git a/tests/useAnswersState.test.tsx b/tests/useSearchState.test.tsx similarity index 82% rename from tests/useAnswersState.test.tsx rename to tests/useSearchState.test.tsx index 5af5b341..1845c5d9 100644 --- a/tests/useAnswersState.test.tsx +++ b/tests/useSearchState.test.tsx @@ -2,18 +2,18 @@ import { act, render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { provideAnswersHeadless, Result, State } from '@yext/answers-headless'; import { useCallback, useReducer } from 'react'; -import { AnswersHeadlessContext, useAnswersActions, useAnswersState } from '../src'; +import { SearchHeadlessContext, useSearchActions, useSearchState } from '../src'; import { renderToString } from 'react-dom/server'; -it('invoke useAnswersState outside of AnswersHeadlessProvider', () => { +it('invoke useSearchState outside of SearchHeadlessProvider', () => { function Test(): JSX.Element { - const query = useAnswersState(state => state.query.input); + const query = useSearchState(state => state.query.input); return
{query}
; } jest.spyOn(global.console, 'error').mockImplementation(); const expectedError = new Error( - 'Attempted to call useAnswersState() outside of AnswersHeadlessProvider.' + - ' Please ensure that \'useAnswersState()\' is called within an AnswersHeadlessProvider component.'); + 'Attempted to call useSearchState() outside of SearchHeadlessProvider.' + + ' Please ensure that \'useSearchState()\' is called within an SearchHeadlessProvider component.'); expect(() => render()).toThrow(expectedError); jest.clearAllMocks(); }); @@ -24,14 +24,14 @@ it('Retrieves state snapshot during server side rendering and hydration process' answers.setVertical('anotherFakeKey'); }); function Test(): JSX.Element { - const verticalKey = useAnswersState(state => state.vertical.verticalKey); + const verticalKey = useSearchState(state => state.vertical.verticalKey); return ; } function App(): JSX.Element { return ( - + - + ); } const renderOnServer = () => renderToString(); @@ -54,8 +54,8 @@ it('does not perform extra renders/listener registrations for nested components' const childStateUpdates: string[] = []; let pendingVerticalQuery; function Test() { - const actions = useAnswersActions(); - const results = useAnswersState(state => { + const actions = useSearchActions(); + const results = useSearchState(state => { return state?.vertical?.results; }) || []; parentStateUpdates.push(results); @@ -73,7 +73,7 @@ it('does not perform extra renders/listener registrations for nested components' } function Child({ results }: { results: Result[] }) { - const queryId = useAnswersState(state => { + const queryId = useSearchState(state => { return state.query.queryId; }) || ''; childStateUpdates.push(queryId); @@ -92,9 +92,9 @@ it('does not perform extra renders/listener registrations for nested components' expect(parentStateUpdates).toHaveLength(0); expect(childStateUpdates).toHaveLength(0); render( - + - + ); expect(addListenerSpy).toHaveBeenCalledTimes(1); expect(parentStateUpdates).toHaveLength(1); @@ -120,20 +120,20 @@ it('does not perform extra renders/listener registrations for nested components' it('does not trigger render on unmounted component', async () => { const consoleSpy = jest.spyOn(console, 'error'); function ParentComponent() { - const results = useAnswersState(state => state.universal?.verticals) || []; + const results = useSearchState(state => state.universal?.verticals) || []; return
{results.map((_, index) => )}
; } function ChildComponent() { - useAnswersState(state => state); + useSearchState(state => state); return
child component
; } const answers = createAnswersHeadless(); render( - + - + ); act(() => answers.setQuery('resultsWithFilter')); await act( async () => { await answers.executeUniversalQuery(); }); @@ -150,7 +150,7 @@ describe('uses the most recent selector', () => { let selector = () => 'initial selector'; function Test() { - const selectedState: string = useAnswersState(selector); + const selectedState: string = useSearchState(selector); const [, triggerRender] = useReducer(s => s + 1, 0); return ( @@ -163,9 +163,9 @@ describe('uses the most recent selector', () => { const answers = createAnswersHeadless(); render( - + - + ); expect(screen.getByTestId('selected-state')).toHaveTextContent('initial selector'); @@ -182,7 +182,7 @@ describe('uses the most recent selector', () => { const stateUpdates: (string | undefined | number)[] = []; function Test() { - const selectedState: string | undefined | number = useAnswersState(selector); + const selectedState: string | undefined | number = useSearchState(selector); const [, triggerRender] = useReducer(s => s + 1, 0); stateUpdates.push(selectedState); @@ -198,9 +198,9 @@ describe('uses the most recent selector', () => { answers.setQuery('initial value'); expect(stateUpdates).toHaveLength(0); render( - + - + ); expect(stateUpdates).toEqual(['initial value']); diff --git a/tsconfig.base.json b/tsconfig.base.json index 53cc339e..a9831fa1 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -2,7 +2,7 @@ "compilerOptions": { "baseUrl": ".", "paths": { - "@yext/answers-headless-react": ["src"] + "@yext/search-headless-react": ["src"] }, "target": "es2015", "esModuleInterop": true, From 4db446b2412ab6d43521a15abced20e9c3737e00 Mon Sep 17 00:00:00 2001 From: Cindy <74145775+ElemelonWind@users.noreply.github.com> Date: Fri, 15 Jul 2022 15:01:56 -0400 Subject: [PATCH 2/5] Answers -> Search 2: rename imports (#144) * renamed answers-headless imports * Automated update to THIRD-PARTY-NOTICES from github action's 3rd party notices check * version update * update license Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- LICENSE | 2 +- THIRD-PARTY-NOTICES | 10 +-- package-lock.json | 92 +++++++++++++-------------- package.json | 6 +- src/SearchHeadlessContext.ts | 4 +- src/SearchHeadlessProvider.tsx | 4 +- src/deprecated.ts | 2 +- src/index.ts | 2 +- src/subscribeToStateUpdates.tsx | 2 +- src/useSearchActions.ts | 10 +-- src/useSearchState.tsx | 2 +- src/useSearchUtilities.ts | 4 +- tests/SearchHeadlessProvider.test.tsx | 10 +-- tests/useSearchState.test.tsx | 4 +- 14 files changed, 77 insertions(+), 77 deletions(-) diff --git a/LICENSE b/LICENSE index 6e1dc0b4..1e04e29a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,7 @@ Contains information from the language-subtag-registry JSON Database (https://github.com/mattcg/language-subtag-registry/tree/master/data/json) which is made available under the ODC Attribution License (https://github.com/mattcg/language-subtag-registry/blob/master/LICENSE.md). -The Answers Headless React files listed in this repository are licensed under the below license. All other features and products are subject to +The Search Headless React files listed in this repository are licensed under the below license. All other features and products are subject to separate agreements and certain functionality requires paid subscriptions to Yext products. BSD 3-Clause License diff --git a/THIRD-PARTY-NOTICES b/THIRD-PARTY-NOTICES index ddaebc26..4790f3f4 100644 --- a/THIRD-PARTY-NOTICES +++ b/THIRD-PARTY-NOTICES @@ -62,11 +62,11 @@ SOFTWARE. The following NPM package may be included in this product: - - @yext/answers-core@1.7.0 + - @yext/search-core@1.8.0 This package contains the following license and notice below: -The Answers Core files listed in this repository are licensed under the below license.  All other features and products are subject to separate agreements +The Search Core files listed in this repository are licensed under the below license.  All other features and products are subject to separate agreements and certain functionality requires paid subscriptions to Yext products. Contains information from the language-subtag-registry JSON Database (https://github.com/mattcg/language-subtag-registry/tree/master/data/json) @@ -106,11 +106,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The following NPM package may be included in this product: - - @yext/answers-headless@1.2.0 + - @yext/search-headless@1.3.0 This package contains the following license and notice below: -The Answers Headless files listed in this repository are licensed under the below license.  All other features and products are subject to separate agreements +The Search Headless files listed in this repository are licensed under the below license.  All other features and products are subject to separate agreements and certain functionality requires paid subscriptions to Yext products. Contains information from the language-subtag-registry JSON Database (https://github.com/mattcg/language-subtag-registry/tree/master/data/json) @@ -118,7 +118,7 @@ which is made available under the ODC Attribution License (https://github.com/ma BSD 3-Clause License -Copyright (c) 2021, Yext +Copyright (c) 2022, Yext All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/package-lock.json b/package-lock.json index dba47ef4..52b71bd7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@yext/search-headless-react", - "version": "1.2.0", + "version": "1.3.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@yext/search-headless-react", - "version": "1.2.0", + "version": "1.3.0", "license": "BSD-3-Clause", "dependencies": { - "@yext/answers-headless": "^1.2.0", + "@yext/search-headless": "^1.3.0", "use-sync-external-store": "^1.1.0" }, "devDependencies": { @@ -4214,29 +4214,6 @@ "node": ">=10.0.0" } }, - "node_modules/@yext/answers-core": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@yext/answers-core/-/answers-core-1.7.0.tgz", - "integrity": "sha512-wOG9TAj3fVUXVJvS5HO+S54O6Ehyd32FfRUtZ4j1kE8ES5T9bhJ8xALos4NC+gCuXIMmV1kHXzsKLafeuSrpAg==", - "dependencies": { - "@babel/runtime-corejs3": "^7.12.5", - "cross-fetch": "^3.1.5" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@yext/answers-headless": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@yext/answers-headless/-/answers-headless-1.2.0.tgz", - "integrity": "sha512-i/TFOfM8izoYu7hala6JRqh6vdhf6gCcIy9Ggh5YIwqkqlUJNQKEyr+O/ZE5tdvOddDizFxTxZvd5yizQC/cSw==", - "dependencies": { - "@reduxjs/toolkit": "^1.8.1", - "@yext/answers-core": "^1.7.0", - "js-levenshtein": "^1.1.6", - "lodash": "^4.17.21" - } - }, "node_modules/@yext/eslint-config-slapshot": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@yext/eslint-config-slapshot/-/eslint-config-slapshot-0.4.0.tgz", @@ -4266,6 +4243,29 @@ "eslint-module-utils": "^2.7.1" } }, + "node_modules/@yext/search-core": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@yext/search-core/-/search-core-1.8.0.tgz", + "integrity": "sha512-t7rg9JZ9K6pIt2nBZ1O+xhzG+zMFVAu9Vgwh8cTey8NA7878cQ6n6BauTwimVdbrNGHq3D2dPUno/kVtKAgPiQ==", + "dependencies": { + "@babel/runtime-corejs3": "^7.12.5", + "cross-fetch": "^3.1.5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@yext/search-headless": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@yext/search-headless/-/search-headless-1.3.0.tgz", + "integrity": "sha512-T5Gvb7MObWTtBPiTIs2WuZgxF44Ro89qiGabl2S1PcN4eQBV3nVVVgFNN1cqCN9K2m4gcm1U9ctAbJyme83vRA==", + "dependencies": { + "@reduxjs/toolkit": "^1.8.1", + "@yext/search-core": "^1.8.0", + "js-levenshtein": "^1.1.6", + "lodash": "^4.17.21" + } + }, "node_modules/abab": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", @@ -15686,26 +15686,6 @@ "version": "0.7.5", "dev": true }, - "@yext/answers-core": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@yext/answers-core/-/answers-core-1.7.0.tgz", - "integrity": "sha512-wOG9TAj3fVUXVJvS5HO+S54O6Ehyd32FfRUtZ4j1kE8ES5T9bhJ8xALos4NC+gCuXIMmV1kHXzsKLafeuSrpAg==", - "requires": { - "@babel/runtime-corejs3": "^7.12.5", - "cross-fetch": "^3.1.5" - } - }, - "@yext/answers-headless": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@yext/answers-headless/-/answers-headless-1.2.0.tgz", - "integrity": "sha512-i/TFOfM8izoYu7hala6JRqh6vdhf6gCcIy9Ggh5YIwqkqlUJNQKEyr+O/ZE5tdvOddDizFxTxZvd5yizQC/cSw==", - "requires": { - "@reduxjs/toolkit": "^1.8.1", - "@yext/answers-core": "^1.7.0", - "js-levenshtein": "^1.1.6", - "lodash": "^4.17.21" - } - }, "@yext/eslint-config-slapshot": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@yext/eslint-config-slapshot/-/eslint-config-slapshot-0.4.0.tgz", @@ -15725,6 +15705,26 @@ "eslint-module-utils": "^2.7.1" } }, + "@yext/search-core": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@yext/search-core/-/search-core-1.8.0.tgz", + "integrity": "sha512-t7rg9JZ9K6pIt2nBZ1O+xhzG+zMFVAu9Vgwh8cTey8NA7878cQ6n6BauTwimVdbrNGHq3D2dPUno/kVtKAgPiQ==", + "requires": { + "@babel/runtime-corejs3": "^7.12.5", + "cross-fetch": "^3.1.5" + } + }, + "@yext/search-headless": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@yext/search-headless/-/search-headless-1.3.0.tgz", + "integrity": "sha512-T5Gvb7MObWTtBPiTIs2WuZgxF44Ro89qiGabl2S1PcN4eQBV3nVVVgFNN1cqCN9K2m4gcm1U9ctAbJyme83vRA==", + "requires": { + "@reduxjs/toolkit": "^1.8.1", + "@yext/search-core": "^1.8.0", + "js-levenshtein": "^1.1.6", + "lodash": "^4.17.21" + } + }, "abab": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", diff --git a/package.json b/package.json index 3beaffa6..5b1007f9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@yext/search-headless-react", - "version": "1.2.0", + "version": "1.3.0", "description": "The official React UI Bindings layer for Search Headless", "main": "./lib/esm/src/index.js", "license": "BSD-3-Clause", @@ -32,7 +32,7 @@ "generate-notices": "generate-license-file --input package.json --output THIRD-PARTY-NOTICES --overwrite" }, "dependencies": { - "@yext/answers-headless": "^1.2.0", + "@yext/search-headless": "^1.3.0", "use-sync-external-store": "^1.1.0" }, "devDependencies": { @@ -84,7 +84,7 @@ "/tests/setup/setup-env.ts" ], "transformIgnorePatterns": [ - "/node_modules/(?!@yext/answers-headless)" + "/node_modules/(?!@yext/search-headless)" ], "transform": { "^.+\\.tsx?$": "ts-jest", diff --git a/src/SearchHeadlessContext.ts b/src/SearchHeadlessContext.ts index bb3a7e6d..0eed077c 100644 --- a/src/SearchHeadlessContext.ts +++ b/src/SearchHeadlessContext.ts @@ -1,5 +1,5 @@ -import { AnswersHeadless } from '@yext/answers-headless'; +import { SearchHeadless } from '@yext/search-headless'; import { createContext } from 'react'; // The default is empty because we don't know the user's config yet -export const SearchHeadlessContext = createContext({} as AnswersHeadless); \ No newline at end of file +export const SearchHeadlessContext = createContext({} as SearchHeadless); \ No newline at end of file diff --git a/src/SearchHeadlessProvider.tsx b/src/SearchHeadlessProvider.tsx index d805f73e..6348446f 100644 --- a/src/SearchHeadlessProvider.tsx +++ b/src/SearchHeadlessProvider.tsx @@ -1,5 +1,5 @@ import { PropsWithChildren } from 'react'; -import { provideAnswersHeadless, AnswersHeadless, HeadlessConfig } from '@yext/answers-headless'; +import { provideHeadless, SearchHeadless, HeadlessConfig } from '@yext/search-headless'; import { SearchHeadlessContext } from './SearchHeadlessContext'; import acquireSessionId from './utils/acquireSessionId'; import packageJson from '../package.json'; @@ -18,7 +18,7 @@ export function SearchHeadlessProvider(props: PropsWithChildren): JSX.Ele ANSWERS_HEADLESS_REACT: version } }; - const answers: AnswersHeadless = provideAnswersHeadless(answersConfig, additionalHttpHeaders); + const answers: SearchHeadless = provideHeadless(answersConfig, additionalHttpHeaders); verticalKey && answers.setVertical(verticalKey); answers.setSessionTrackingEnabled(sessionTrackingEnabled); diff --git a/src/deprecated.ts b/src/deprecated.ts index bcacf2e3..c2cd3477 100644 --- a/src/deprecated.ts +++ b/src/deprecated.ts @@ -4,7 +4,7 @@ import { useSearchUtilities, SearchUtilities } from './useSearchUtilities'; import { SearchHeadlessProvider } from './SearchHeadlessProvider'; import { SearchHeadlessContext } from './SearchHeadlessContext'; import { PropsWithChildren } from 'react'; -import { HeadlessConfig } from '@yext/answers-headless'; +import { HeadlessConfig } from '@yext/search-headless'; type Props = HeadlessConfig & { verticalKey?: string, diff --git a/src/index.ts b/src/index.ts index 040eee4e..bbc95ac1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,7 +5,7 @@ import { subscribeToStateUpdates } from './subscribeToStateUpdates'; import { SearchHeadlessProvider } from './SearchHeadlessProvider'; import { SearchHeadlessContext } from './SearchHeadlessContext'; -export * from '@yext/answers-headless'; +export * from '@yext/search-headless'; export * from './deprecated'; export { SearchHeadlessContext, diff --git a/src/subscribeToStateUpdates.tsx b/src/subscribeToStateUpdates.tsx index 7cebd1f0..efe19971 100644 --- a/src/subscribeToStateUpdates.tsx +++ b/src/subscribeToStateUpdates.tsx @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { ComponentType, useReducer, useEffect, useContext } from 'react'; -import { State } from '@yext/answers-headless'; +import { State } from '@yext/search-headless'; import { SearchHeadlessContext } from './SearchHeadlessContext'; import isShallowEqual from './utils/isShallowEqual'; diff --git a/src/useSearchActions.ts b/src/useSearchActions.ts index 746d2b34..303c43de 100644 --- a/src/useSearchActions.ts +++ b/src/useSearchActions.ts @@ -1,14 +1,14 @@ -import { AnswersHeadless } from '@yext/answers-headless'; +import { SearchHeadless } from '@yext/search-headless'; import { useContext } from 'react'; import { SearchHeadlessContext } from './SearchHeadlessContext'; -export type SearchActions = AnswersHeadless; +export type SearchActions = SearchHeadless; export function useSearchActions(): SearchActions { - const answersHeadless = useContext(SearchHeadlessContext); - if (answersHeadless.state === undefined) { + const searchHeadless = useContext(SearchHeadlessContext); + if (searchHeadless.state === undefined) { throw new Error('Attempted to call useSearchActions() outside of SearchHeadlessProvider.' + ' Please ensure that \'useSearchActions()\' is called within an SearchHeadlessProvider component.'); } - return answersHeadless; + return searchHeadless; } \ No newline at end of file diff --git a/src/useSearchState.tsx b/src/useSearchState.tsx index 9615368d..a0501fa1 100644 --- a/src/useSearchState.tsx +++ b/src/useSearchState.tsx @@ -1,5 +1,5 @@ import { useCallback, useContext, useEffect, useRef } from 'react'; -import { State } from '@yext/answers-headless'; +import { State } from '@yext/search-headless'; import { SearchHeadlessContext } from './SearchHeadlessContext'; import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/shim/with-selector'; diff --git a/src/useSearchUtilities.ts b/src/useSearchUtilities.ts index 1cc4cb8a..eb9d51ad 100644 --- a/src/useSearchUtilities.ts +++ b/src/useSearchUtilities.ts @@ -1,8 +1,8 @@ -import { AnswersHeadless } from '@yext/answers-headless'; +import { SearchHeadless } from '@yext/search-headless'; import { useContext } from 'react'; import { SearchHeadlessContext } from './SearchHeadlessContext'; -export type SearchUtilities = AnswersHeadless['utilities']; +export type SearchUtilities = SearchHeadless['utilities']; export function useSearchUtilities(): SearchUtilities { return useContext(SearchHeadlessContext).utilities; diff --git a/tests/SearchHeadlessProvider.test.tsx b/tests/SearchHeadlessProvider.test.tsx index bd5c5040..234a5f1a 100644 --- a/tests/SearchHeadlessProvider.test.tsx +++ b/tests/SearchHeadlessProvider.test.tsx @@ -1,9 +1,9 @@ import { SearchHeadlessProvider, SandboxEndpoints } from '../src'; import { render } from '@testing-library/react'; -import { provideAnswersHeadless } from '@yext/answers-headless'; +import { provideHeadless } from '@yext/search-headless'; -jest.mock('@yext/answers-headless', () => ({ - provideAnswersHeadless: jest.fn(() => ({ +jest.mock('@yext/search-headless', () => ({ + provideHeadless: jest.fn(() => ({ setSessionTrackingEnabled: jest.fn(), setSessionId: jest.fn() })) @@ -18,6 +18,6 @@ it('correctly passes through an answers config with sandbox endpoints', () => { }; render(); - expect(provideAnswersHeadless).toHaveBeenCalledTimes(1); - expect(provideAnswersHeadless).toHaveBeenCalledWith(config, expect.anything()); + expect(provideHeadless).toHaveBeenCalledTimes(1); + expect(provideHeadless).toHaveBeenCalledWith(config, expect.anything()); }); \ No newline at end of file diff --git a/tests/useSearchState.test.tsx b/tests/useSearchState.test.tsx index 1845c5d9..5e82d49e 100644 --- a/tests/useSearchState.test.tsx +++ b/tests/useSearchState.test.tsx @@ -1,6 +1,6 @@ import { act, render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { provideAnswersHeadless, Result, State } from '@yext/answers-headless'; +import { provideHeadless, Result, State } from '@yext/search-headless'; import { useCallback, useReducer } from 'react'; import { SearchHeadlessContext, useSearchActions, useSearchState } from '../src'; import { renderToString } from 'react-dom/server'; @@ -220,7 +220,7 @@ describe('uses the most recent selector', () => { }); function createAnswersHeadless() { - return provideAnswersHeadless({ + return provideHeadless({ apiKey: 'fake api key', experienceKey: 'fake exp key', locale: 'en', From 6a60302929e144f77fce21a41d22aa2248c2ed8a Mon Sep 17 00:00:00 2001 From: Cindy Yang Date: Mon, 18 Jul 2022 12:53:02 -0400 Subject: [PATCH 3/5] rebase w develop --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 52b1e4fb..80476173 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ function SearchBar() { ## `SearchHeadlessContext` ## Class Components -For users that want to use class components instead of functional components, you can use the `SearchHeadlessContext` directly to dispatch actions, and the `subscribeToStateUpdates` HOC to receive updates from state. +For users that want to use class components instead of functional components, you can use the `SearchHeadlessContext` directly to dispatch actions and receive updates from state. As an example, here is our simple SearchBar again, rewritten as a class using `SearchHeadlessContext`. From a0797eae2b7d98b10f3183415ef073ed6c64174a Mon Sep 17 00:00:00 2001 From: Cindy Yang Date: Tue, 19 Jul 2022 09:56:51 -0400 Subject: [PATCH 4/5] fix typos --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 80476173..8ccabd09 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ function MyApp() { ```tsx import { useSearchState } from '@yext/search-headless-react'; - default function MostRecentSearch() { +export default function MostRecentSearch() { const mostRecentSearch = useSearchState(state => state.query.mostRecentSearch); return
Showing results for {mostRecentSearch}
; } @@ -91,7 +91,7 @@ function SearchBar() { ``` ## `SearchHeadlessContext` -## Class Components +### Class Components For users that want to use class components instead of functional components, you can use the `SearchHeadlessContext` directly to dispatch actions and receive updates from state. From ab0e4048d79ae28c1a06f1aa4ac40cc2a268635e Mon Sep 17 00:00:00 2001 From: Cindy Yang Date: Tue, 19 Jul 2022 11:51:40 -0400 Subject: [PATCH 5/5] addressed nits --- src/deprecated.ts | 4 ++-- src/subscribeToStateUpdates.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/deprecated.ts b/src/deprecated.ts index c2cd3477..0661235c 100644 --- a/src/deprecated.ts +++ b/src/deprecated.ts @@ -39,12 +39,12 @@ export function useAnswersState(stateSelector: StateSelector): T { } /** - * @deprecated useAnswersUtilities has been deprecated and repalced by useSearchUtilities + * @deprecated useAnswersUtilities has been deprecated and replaced by useSearchUtilities */ export function useAnswersUtilities(): SearchUtilities { return useSearchUtilities(); } /** - * @deprecated AnswersHeadlessProvider has been deprecated and replaced by SearfchHeadlessProvider + * @deprecated AnswersHeadlessProvider has been deprecated and replaced by SearchHeadlessProvider */ export function AnswersHeadlessProvider(props: PropsWithChildren): JSX.Element { return SearchHeadlessProvider(props); diff --git a/src/subscribeToStateUpdates.tsx b/src/subscribeToStateUpdates.tsx index efe19971..5681e953 100644 --- a/src/subscribeToStateUpdates.tsx +++ b/src/subscribeToStateUpdates.tsx @@ -11,8 +11,8 @@ type SubscriberGenerator = (WrappedComponent: ComponentType) => (props: any * search-headless state and a given mapping function. * * @deprecated - * For class component, use `SearchHeadlessContext` directly to dispatch actions and receive state updates. - * For functional component, use `useSearchActions` and `useSearchState` instead. + * For class components, use `SearchHeadlessContext` directly to dispatch actions and receive state updates. + * For functional components, use `useSearchActions` and `useSearchState` instead. */ export function subscribeToStateUpdates( mapStateToProps: (s: State) => Record