1.0.0-rc1 • Published 2 years ago

react-hooks-provider v1.0.0-rc1

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

react-hooks-provider

Share hooks between components

Install

npm install react-hooks-provider

Examples

Example on CodeSandbox

How it works

Some hooks are tied to a specific component, but others should share their state between any consuming component. It is quite a ceremony to share hook state between components by creating and exposing the hook on a context. react-hooks-provider gives you a single provider with a simple API to expose any hook as a shared hook between components.

Every hook registered with the provider will receive the props passed to the provider, which allows you to configure your hooks for a certain session, environment etc. Each hook will internally get their own context, ensuring optimal reconciliation.

Additional utilities allows you to create a consumer component and mock the hook for testing purposes.

API

createHooksProvider

hooks/index.ts

import { createHooksProvider } from "react-hooks-provider";

// Any props passed to the Provider component, which will be
// passed to all registered hooks
type Props = {};

const { registerHook, Provider } = createHooksProvider<Props>();

export { registerHook, Provider };

hooks/useCount.ts

import { registerHook } from ".";

export const useCount = registerHook(() => useState(0));

// Derive a value from an existing hook, which ensures the consuming
// component will only reconcile if the derived value has changed
export const useSetCount = registerHook(useCount, [, setCount] => setCount)

components/App.tsx

import { Provider as HooksProvider } from "./hooks";

export const App: React.FC = () => {
  <HooksProvider>
    <Content />
  </HooksProvider>;
};

createHookConsumer

hooks/useCount.ts

import { createHookConsumer } from "react-hooks-provider";
import { registerHook } from ".";

export const useCount = registerHook(() => useState(0));

export const CountConsumer = createHookConsumer(useCount);

getHookProvider

hooks/useCount.test.ts

import { render, screen } from "@testing-library/react";
import { getHookProvider } from "react-hooks-provider";
import { useCount } from "./useCount";

const MockedCount = getHookProvider(useCount);

test("should show count in heading", () => {
  const setCount = jest.fn();
  const { result } = render(<SomeCountConsumer />, {
    wrapper: ({ children }) => (
      <MockedCount value={[5, setCount]}>{children}</MockedCount>
    ),
  });

  expect(screen.getByRole("heading")).toHaveTextContent("5");
});