1.1.1 • Published 10 months ago

react-context-store v1.1.1

Weekly downloads
116
License
MIT
Repository
github
Last release
10 months ago

React context store

A two way binding mechanism that uses React context as a storage machanism.

For small to medium sized apps I found redux to be a bit heavy for what it achieved. In reality, most of the time I want to create a simple website that blocks the form submit as a network call is being processed.

Basic usage

The following documentation has been copied out of a test case. If you find that it's not working, please check the test case. This example is an array but you can also use maps, or store a non-indexable type.

First create the context store

import React, { PropsWithChildren } from "react";

import {
  ContextStore,
  useIndexableContextStore,
  getNotImplementedPromise,
} from "@tesla/react-context-store";

export type Item = {
  id: number,
  name: string,
};

type ContextStoreDataArray = Array<Item>;

export type GetAllParams = ContextStoreDataArray;
export interface ContextValue extends ContextStore<ContextStoreDataArray> {
  getAll: (params: GetAllParams) => Promise<ContextStoreDataArray>;
}

const defaultValue: ContextValue = {
  data: [],
  getAll: getNotImplementedPromise,
  state: "unsent",
};

export const Context = React.createContext(defaultValue);
export type ApiProviderProps = PropsWithChildren<{}>;

export function ApiProvider(props: ApiProviderProps) {
  const { children } = props;
  const [
    contextValue,
    {
      useUpdateFactory,
      useUpdateOneFactory,
      useCreateOneFactory,
      useDeleteOneFactory,
    },
  ] = useIndexableContextStore(defaultValue);

  const getAll = useUpdateFactory({
    action: (params: GetAllParams) => {
      return await fetchList(params);
    },
  });

  return (
    <Context.Provider
      value={{ ...contextValue, getAll }}
    >
      {children}
    </Context.Provider>
  );
}

Somewhere in your app, setup the shared provider

import { ApiProvider, Context } from "../context";
import { List } from "./component";

export function App() {
  return (
    <ApiProvider>
      <List />
    </ApiProvider>
  );
}

And finally consume the context

import { ApiProvider, Context } from "../context";

export function List() {
  const { data, getAll, state } = useContext(Context);

  useEffect(() => {
    getAll();
  });

  switch (state) {
    case "error":
      return <div>Oh no!</div>;
    case "success":
      return (
        <div>
          <ul>
            {data.map((item) => {
              const { id, name } = item;
              return <li key={id}>{name}</li>;
            })}
          </ul>
        </div>
      );
    default:
      return <div>Loading</div>;
  }
}

For more examples, take a look at our extensive testing suite.

API

There are two types of store hooks both of which return the current store contents and the available modifiers.

  • useContextStore - For non-indexable stores like objects and primatives
  • useIndexableContextStore - For indexable stores like maps or arrays
  • useStatefulIndexableContextStore - For indexable stores but when you want to maintain separate load states per item than the list of items

Both come with the following modifiers:

  • useUpdateFactory - Used to modify all the values in the store at once. Useful for getAll, deleteAll, modifyAll, etc.
  • setContextData - Used to create custom modifiers if for some reason you don't like ours.

They also have the same states:

  • unsent - No modifier has acted upon the data
  • loading - The modifier has been invoked but the action hasn't completed yet
  • success - The action was successful and the data has been updated
  • error - The action failed

The useIndexableContextStore has an additional update methods that affect individual items each of which have their own state:

  • useUpdateOneFactory - Used to create an updater which modifies an existing entry - PUT calls
  • useCreateOneFactory - Used to create a creator which creates a new entry - GET and POST calls.
  • useDeleteOneFactory - Used to create a deletor which removes an entry - DELETE call

The useStatefulIndexableContextStore has the same methods as above however each item in the index will have a load state. When any of the use___OneFactory functions are used, the list's load state doesn't change however the individual item's load state does.

1.2.0-beta.1

10 months ago

1.2.0-beta.0

10 months ago

1.1.1

2 years ago

1.1.0

3 years ago

1.1.0-beta.0

3 years ago

1.0.0

3 years ago

1.0.0-beta.6

3 years ago

1.0.0-beta.5

3 years ago

1.0.0-beta.4

3 years ago

1.0.0-beta.3

3 years ago

1.0.0-beta.2

3 years ago

1.0.0-beta.0

3 years ago

0.1.0

7 years ago

0.0.5

7 years ago

0.0.4

7 years ago

0.0.3

7 years ago

0.0.2

7 years ago

0.0.1

7 years ago