Skip to content
This repository has been archived by the owner on Jul 7, 2022. It is now read-only.
/ context-model Public archive

A simple wrapper for the React Context API.

License

Notifications You must be signed in to change notification settings

jorenrui/context-model

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Context Model

A personal context API wrapper for state management driven by the desire to learn more and experiment.

2.0.2 NPM Version MIT License Status

A simple wrapper for the Context API.

Installation

Install it using yarn or npm:

# Using NPM
npm install --save context-model

# Using Yarn
yarn add context-model

Usage

Creating a Store

JavaScript

First define the Context Model:

// ANCHOR React
import { useState } from 'react';

// ANCHOR Model
import createStore from 'context-model';

/**
 * ANCHOR Counter
 * Creating a Counter context model using `createStore`.
 * `contextModel` will return an object with `Provider` and `useStore` methods.
 */
const Counter = createStore(({ initialCount }) => {
    const [count, setCount] = useState(initialCount ?? 0);

    const increment = () => {
      setCount((count) => count + 1);
    }

    const decrement = () => {
      setCount((count) => count - 1);
    }

    const reset = () => {
      setCount(0);
    }

    return {
      count,
      increment,
      decrement,
      reset,
    }
  },
);

export default Counter;

TypeScript

First define the Context Model:

// ANCHOR React
import { useState } from 'react';

// ANCHOR Model
import createStore from 'context-model';

/**
 * ANCHOR IProps
 * This will be the basis for the type of
 * the context model's provider component
 *
 * The following example makes the initialCount
 * prop optional
 */
interface IProps {
  initialCount?: number;
}

/**
 * ANCHOR Counter
 * Creating a Counter context model using `createStore`.
 * `contextModel` will return an object with `Provider` and `useStore` methods.
 */
const Counter = createStore(({ initialCount }: IProps) => {
    const [count, setCount] = React.useState(initialCount ?? 0);

    const increment = () => {
      setCount((count) => count + 1);
    }

    const decrement = () => {
      setCount((count) => count - 1);
    }

    const reset = () => {
      setCount(0);
    }

    return {
      count,
      increment,
      decrement,
      reset,
    }
  },
);

export default Counter;

Adding the Provider

To allow the consumption of the context, add the Provider to the component tree.

function App() {
  return (
    <Counter.Provider>
      <Count />
      <Controls />
    </Counter.Provider>
  );
}

useStore hook

To consume the context, you may use the useStore hook. This returns the state object.

function Count() {
  const { count } = Counter.useStore();

  return <h1>{count}</h1>
}

function Controls() {
  const { increment, decrement, reset } = Counter.useStore();

  return (
    <>
      <button onClick={increment}>increment</button>
      <button onClick={decrement}>decrement</button>
      <button onClick={reset}>reset</button>
    </>
  );
}

useStore can be use in the following ways:

// Getting the state object
const store = Counter.useStore();

// Deconstructing the state object
const { count, reset } = Counter.useStore();

useSelector hook

To consume and transform the context, you may use the useSelector hook. This takes in a selector function as its props then returns a value based on the given function.

// Providing a callback function that transforms the store value
const count = Counter.useSelector((state) => state.count + 10);
const [incrementedCount, decrementedCount] = Counter.useSelector((state) => [
  state.count + 1,
  state.count - 1,
]);

// Or you can do it like this 👀
function addTen(number) {
  return number + 10;
}

const count = Counter.useSelector((state) => addTen(state.number));

// This callback function is also useful for picking specific value(s) from the store like so:
const count = Counter.useSelector((state) => state.count);

Options

For better experience in debugging using the Dev Tools, you may add the displayName of the context model. In this case I named the model as Counter:

const Counter = createStore((state) => state, {
  displayName: 'Counter',
});

Inspirations

Being new to React, I wanted to learn more about state management. Thus I decided to try my hand on it by creating a simple wrapper for the Context API. The react-scoped-model inspired the structure of this wrapper, namely the usage of useSelector and Provider.

A list of all things Context API. You might want to check it out if you're also curious to learn more 👀.

Changelog

Changelog

License

MIT © Joeylene Rivera