Skip to content

Commit

Permalink
Chat-headless-react: Surface overridable instance (#34)
Browse files Browse the repository at this point in the history
  • Loading branch information
nbramblett authored Aug 18, 2023
1 parent eb77657 commit 436421f
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 36 deletions.
22 changes: 2 additions & 20 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions packages/chat-headless-react/THIRD-PARTY-NOTICES
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The following npm packages may be included in this product:

- @yext/chat-core@0.5.5
- @yext/chat-headless@0.5.8
- @yext/chat-core@0.6.1
- @yext/chat-headless@0.6.0

These packages each contain the following license and notice below:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

## ChatHeadlessProvider() function

Instantiates a ChatHeadless instance for [ChatHeadlessContext](./chat-headless-react.chatheadlesscontext.md) and provide the context for all children components.
Instantiates a ChatHeadless instance for [ChatHeadlessContext](./chat-headless-react.chatheadlesscontext.md) and provides the context to all children components.

**Signature:**

Expand Down
2 changes: 1 addition & 1 deletion packages/chat-headless-react/docs/chat-headless-react.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

| Function | Description |
| --- | --- |
| [ChatHeadlessProvider(props)](./chat-headless-react.chatheadlessprovider.md) | Instantiates a ChatHeadless instance for [ChatHeadlessContext](./chat-headless-react.chatheadlesscontext.md) and provide the context for all children components. |
| [ChatHeadlessProvider(props)](./chat-headless-react.chatheadlessprovider.md) | Instantiates a ChatHeadless instance for [ChatHeadlessContext](./chat-headless-react.chatheadlesscontext.md) and provides the context to all children components. |
| [useChatActions()](./chat-headless-react.usechatactions.md) | A React hook that returns a ChatHeadless instance with setter methods to update state. |
| [useChatState(stateSelector)](./chat-headless-react.usechatstate.md) | A React hook that returns a Chat state in store as specified by the map function. |

Expand Down
4 changes: 2 additions & 2 deletions packages/chat-headless-react/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@yext/chat-headless-react",
"version": "0.5.8",
"version": "0.5.9",
"description": "the official React UI Bindings layer for Chat Headless",
"main": "./dist/commonjs/src/index.js",
"module": "./dist/esm/src/index.js",
Expand Down Expand Up @@ -39,7 +39,7 @@
"homepage": "https://github.com/yext/chat-headless#readme",
"dependencies": {
"@reduxjs/toolkit": "^1.9.5",
"@yext/chat-headless": "^0.5.8",
"@yext/chat-headless": "^0.6.0",
"react-redux": "^8.0.5"
},
"peerDependencies": {
Expand Down
58 changes: 48 additions & 10 deletions packages/chat-headless-react/src/ChatHeadlessProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { ChatHeadless, HeadlessConfig } from "@yext/chat-headless";
import {
provideChatHeadless,
ChatHeadless,
HeadlessConfig,
} from "@yext/chat-headless";
import { PropsWithChildren, useMemo, useEffect, useState } from "react";
import { Provider } from "react-redux";
import { ChatHeadlessContext } from "./ChatHeadlessContext";
Expand All @@ -14,8 +18,8 @@ export type ChatHeadlessProviderProps = PropsWithChildren<{
}>;

/**
* Instantiates a ChatHeadless instance for {@link ChatHeadlessContext} and provide
* the context for all children components.
* Instantiates a ChatHeadless instance for {@link ChatHeadlessContext} and provides
* the context to all children components.
*
* @param props - {@link ChatHeadlessProviderProps}
*
Expand All @@ -25,27 +29,61 @@ export function ChatHeadlessProvider(
props: ChatHeadlessProviderProps
): JSX.Element {
const { children, config } = props;
// deferLoad is used with sessionStorage so that the children won't be
// immediately rendered and trigger the "load initial message" flow before
// the state can be loaded from session.
const [deferLoad, setDeferLoad] = useState(config.saveToSessionStorage);

const headless = useMemo(() => {
const configWithoutSession = { ...config, saveToSessionStorage: false };
const headless = new ChatHeadless(updateClientSdk(configWithoutSession));
const headless = provideChatHeadless(updateClientSdk(configWithoutSession));
return headless;
}, [config]);

return (
<ChatHeadlessInstanceProvider
deferRender={config.saveToSessionStorage}
headless={headless}
>
{children}
</ChatHeadlessInstanceProvider>
);
}

/**
* Props for {@link ChatHeadlessInstanceProvider}
*
* @internal
*/
export type ChatHeadlessInstanceProviderProps = PropsWithChildren<{
// Set this to true when using server-side rendering in conjunction with
// browser-specific APIs like session storage.
deferRender?: boolean;
headless: ChatHeadless;
}>;

/**
* Takes in a ChatHeadless instance for {@link ChatHeadlessContext} and provides
* the context to all children components.
* @param props - {@link ChatHeadlessInstanceProviderProps}
*
* @internal
*/
export function ChatHeadlessInstanceProvider(
props: ChatHeadlessInstanceProviderProps
): JSX.Element {
const { children, deferRender, headless } = props;
// deferLoad is typically used with sessionStorage so that the children won't be
// immediately rendered and trigger the "load initial message" flow before
// the state can be loaded from session.
const [deferLoad, setDeferLoad] = useState(deferRender);

// sessionStorage is overridden here so that it is compatible with server-
// side rendering, which cannot have browser api calls like session storage
// outside of hooks.
useEffect(() => {
if (!config.saveToSessionStorage || !headless) {
if (!deferRender || !headless) {
return;
}
headless.initSessionStorage();
setDeferLoad(false);
}, [headless, config]);
}, [headless, deferRender]);

return (
<ChatHeadlessContext.Provider value={headless}>
Expand Down

0 comments on commit 436421f

Please sign in to comment.