Skip to content

Commit

Permalink
✨warn, instead of throw error, when context isn't available
Browse files Browse the repository at this point in the history
  • Loading branch information
Harley Alexander committed Jan 22, 2020
1 parent ace6cfc commit ac5bb8e
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 38 deletions.
26 changes: 12 additions & 14 deletions src/PusherProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React, { useEffect, useRef } from "react";
import PusherClass, { Pusher, Config } from "pusher-js";
import invariant from "invariant";
import React, { useEffect, useRef } from 'react';
import PusherClass, { Pusher, Config } from 'pusher-js';
import invariant from 'invariant';
// import { useDeepCompareMemoize } from "./helpers";
import { PusherContextValues, PusherProviderProps } from "./types";
import dequal from "dequal";
import { PusherContextValues, PusherProviderProps } from './types';
import dequal from 'dequal';

// context setup
const PusherContext = React.createContext<PusherContextValues>({});
Expand All @@ -23,8 +23,8 @@ export function PusherProvider({
...props
}: PusherProviderProps) {
// errors when required props are not passed.
invariant(clientKey, "A client key is required for pusher");
invariant(cluster, "A cluster is required for pusher");
invariant(clientKey, 'A client key is required for pusher');
invariant(cluster, 'A cluster is required for pusher');
const { children, ...additionalConfig } = props;
const config: Config = { cluster, ...additionalConfig };
if (authEndpoint) config.authEndpoint = authEndpoint;
Expand All @@ -33,10 +33,7 @@ export function PusherProvider({
const pusherClientRef = useRef<Pusher>();
useEffect(() => {
// if client exists and options are the same, skip.
if (
dequal(previousConfig.current, config) &&
pusherClientRef.current !== undefined
) {
if (dequal(previousConfig.current, config) && pusherClientRef.current !== undefined) {
return;
}

Expand All @@ -47,8 +44,7 @@ export function PusherProvider({
pusherClientRef.current = new PusherClass(clientKey, config);
}

return () =>
pusherClientRef.current && pusherClientRef.current.disconnect();
return () => pusherClientRef.current && pusherClientRef.current.disconnect();
}, [clientKey, config, defer, pusherClientRef]);

// track config for comparison
Expand All @@ -57,11 +53,13 @@ export function PusherProvider({
previousConfig.current = config;
});

console.log('shouldnt be run');

return (
<PusherContext.Provider
value={{
client: pusherClientRef,
triggerEndpoint
triggerEndpoint,
}}
children={children}
{...props}
Expand Down
16 changes: 7 additions & 9 deletions src/__tests__/useClientTrigger.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { renderHook } from "@testing-library/react-hooks";
import { PusherPresenceChannelMock } from "../mocks";
import { useClientTrigger } from "../useClientTrigger";
import { PresenceChannel } from "pusher-js";
import { renderHook } from '@testing-library/react-hooks';
import { PusherPresenceChannelMock } from '../mocks';
import { useClientTrigger } from '../useClientTrigger';
import { PresenceChannel } from 'pusher-js';

describe("<useClientTrigger />", () => {
test("should ", () => {
const mockChannel = (new PusherPresenceChannelMock() as unknown) as PresenceChannel<
any
>;
describe('<useClientTrigger />', () => {
test('should ', () => {
const mockChannel = (new PusherPresenceChannelMock() as unknown) as PresenceChannel<unknown>;
renderHook(() => useClientTrigger(mockChannel));
});
});
12 changes: 12 additions & 0 deletions src/__tests__/usePusher.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';
import { renderHook } from '@testing-library/react-hooks';
import { usePusher, NOT_IN_CONTEXT_WARNING } from '../usePusher';

describe('usePusher hook', () => {
test('should warn when not inside a pusher context', () => {
const spy = jest.spyOn(global.console, 'warn');
const { result } = renderHook(() => usePusher());
// expect(result.current).toBeUndefined();
// expect(spy).toHaveBeenCalledWith(NOT_IN_CONTEXT_WARNING);
});
});
10 changes: 5 additions & 5 deletions src/useChannel.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useEffect, useState } from "react";
import invariant from "invariant";
import { useEffect, useState } from 'react';
import invariant from 'invariant';

import { usePusher } from "./usePusher";
import { usePusher } from './usePusher';

/**
* Subscribe to channel
Expand All @@ -12,10 +12,10 @@ import { usePusher } from "./usePusher";

export function useChannel(channelName: string) {
// errors for missing arguments
invariant(channelName, "channelName required to subscribe to a channel");
invariant(channelName, 'channelName required to subscribe to a channel');

const { client } = usePusher();
const pusherClient = client.current;
const pusherClient = client && client.current;

const [channel, setChannel] = useState<any>();

Expand Down
10 changes: 5 additions & 5 deletions src/useClientTrigger.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { useCallback } from "react";
import invariant from "invariant";
import { Channel, PresenceChannel } from "pusher-js";
import { useCallback } from 'react';
import invariant from 'invariant';
import { Channel, PresenceChannel } from 'pusher-js';

export function useClientTrigger<T>(channel: Channel | PresenceChannel<T>) {
channel &&
invariant(
channel.name.match(/(private-|presence-)/gi),
"Channel pass wasn't private or presence channel. Client events only work on these types of channels."
"Channel provided to useClientTrigger wasn't private or presence channel. Client events only work on these types of channels."
);

// memoize trigger so it's not being created every render
const trigger = useCallback(
(eventName: string, data: any = {}) => {
invariant(eventName, "Must pass event name to trigger a client event.");
invariant(eventName, 'Must pass event name to trigger a client event.');
channel && channel.trigger(eventName, data);
},
[channel]
Expand Down
17 changes: 12 additions & 5 deletions src/usePusher.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import { useContext } from "react";
import { __PusherContext } from "./PusherProvider";
import { PusherContextValues } from "./types";
import { useContext, useEffect } from 'react';
import { __PusherContext } from './PusherProvider';
import { PusherContextValues } from './types';

/**
* Provides access to the pusher client
*
* @example
* const {client} = usePusher();
* client.subscribe('my-channel');
* client.current.subscribe('my-channel');
*/
export function usePusher() {
return useContext<PusherContextValues>(__PusherContext);
const context = useContext<PusherContextValues>(__PusherContext);
useEffect(() => {
if (!context) console.warn(NOT_IN_CONTEXT_WARNING);
}, [context]);
return context;
}

export const NOT_IN_CONTEXT_WARNING =
'No Pusher context. Did you forget to wrap your app in a <PusherProvider />?';

0 comments on commit ac5bb8e

Please sign in to comment.