use-partial-context

NPM Version Size codecov.io Code Coverage GitHub stars

usePartialContext

React hook that provides ability to use only part of context, preventing unnecessary updates.

npm i use-partial-context

demo

examples

Usage

const Context = createPartialContext();

const Row = memo(() => {
    const value = Context.usePartialContext(data => data.smth);

    // component will be updated ONLY if value changes
    return <div>{value}</div>;
});

function MyApp() {
    const store = useState(...);
    return <Context.Provider value={store}>{/** render rows */}</Ctx.Provider>;
}

Examples

Results are memoized by fields, not just by reference:

const value = Context.usePartialContext((row) => ({
    x: row.foo,
    y: row.boo,
}));

Pass deps of your getter function to force update:

const [counter] = useState();
const value = Context.usePartialContext(
    (data) => data.smth + counter,
    [counter]
);

Pass custom comparison function for memoization (by default is good btw):

const value = Context.usePartialContext(
    getter,
    deps,
    (nextValue, prevValue) => nextValue === prevValue
);

Decide when to update based on prev result:

const value = Context.usePartialContext((ctxData, prevResult) => {
    // no updates, everything is ok
    if (prevResult.status === "ok") return prevResult;

    // waiting
    if (ctxData.loading) return { status: "not ok" };

    // loaded, pick data
    return { status: "ok", data: ctxData.data.smth };
});

Prevent getter calls by comparing incoming data:

const value = Context.usePartialContext(
    getter,
    deps,
    undefined,
    // do not call getter while `smth` inside context is equal
    (nextCtx, prevCtx) => nextCtx.smth === prevCtx.smth
);

Api

createPartialContext<T>() returns context object:

{
    Provider
    usePartialContext
    Consumer
    useContext
}

context.usePartialContext(getter, deps?, isEqual?, isDataEqual?)

context.usePartialContext<Result>(
    getter: (contextData: ContextDataT, prevResult?: Result): Result,
    deps?: any[],
    isEqual?: (next: Result, prev: Result): boolean,
    isDataEqual?: (next: ContextDataT, prev: ContextDataT): boolean
): R

getter transforms value from context to result.
deps is used to force get new value from context with new getter function.
isEqual is custom comparison method for result value.
isDataEqual is custom comparison method for incoming context data.

Alternatives

As an alternative there is use-context-selector but: