react-app-modules
Advanced tools
Comparing version 1.0.1 to 1.0.2
{ | ||
"name": "react-app-modules", | ||
"version": "1.0.1", | ||
"version": "1.0.2", | ||
"main": "dist/index.js", | ||
@@ -5,0 +5,0 @@ "types": "dist/index.d.ts", |
197
README.md
@@ -5,2 +5,10 @@ # react-app-modules | ||
[![Latest Stable Version](https://img.shields.io/npm/v/react-app-modules.svg)](https://www.npmjs.com/package/react-app-modules) | ||
[![NPM Downloads](https://img.shields.io/npm/dm/react-app-modules.svg)](https://www.npmjs.com/package/react-app-modules) | ||
[![NPM Downloads](https://img.shields.io/npm/dt/react-app-modules.svg)](https://www.npmjs.com/package/react-app-modules) | ||
[![Bundlephobia Size](https://img.shields.io/bundlephobia/minzip/react-app-modules.svg)](https://www.npmjs.com/package/react-app-modules) | ||
[![Dependency Status](https://img.shields.io/david/rrogowski/react-app-modules.svg)](https://david-dm.org/rrogowski/react-app-modules) | ||
[![License](https://img.shields.io/npm/l/react-app-modules.svg?style=flat)](https://david-dm.org/rrogowski/react-app-modules?type=peer) | ||
### Features | ||
@@ -19,8 +27,21 @@ | ||
--- | ||
## Table of Contents | ||
<!-- START doctoc generated TOC please keep comment here to allow auto update --> | ||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> | ||
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* | ||
- [Installation](#installation) | ||
- [Tutorial](#tutorial) | ||
- [Setup](#setup) | ||
- [Directory Structure](#directory-structure) | ||
- [Defining a Module](#defining-a-module) | ||
- [Defining the Symbols](#defining-the-symbols) | ||
- [Defining a Provider](#defining-a-provider) | ||
- [Defining an Example Component](#defining-an-example-component) | ||
- [Creating the Container / Context](#creating-the-container--context) | ||
- [Checking the Results](#checking-the-results) | ||
- [Api](#api) | ||
- [Development](#development) | ||
@@ -31,2 +52,4 @@ - [Dependencies](#dependencies) | ||
- [Publish](#publish) | ||
- [Misc](#misc) | ||
- [Update README Table of Contents](#update-readme-table-of-contents) | ||
@@ -47,4 +70,174 @@ <!-- END doctoc generated TOC please keep comment here to allow auto update --> | ||
Coming soon... | ||
This tutorial will demonstrate how to use `react-app-modules` | ||
to define, provide, and use a simple `ICalculator` module. | ||
It is recommended that the reader follows this tutorial by | ||
typing along (rather than copying / pasting) to get a sense | ||
of the type-safety that this library provides. Feel emboldened | ||
to try to use the api incorrectly; see for yourself what happens! | ||
### Setup | ||
```bash | ||
# create a new React app | ||
npx create-react-app tutorial --template typescript | ||
# enter the newly created directory | ||
cd tutorial | ||
# add this lovely package as a dependency | ||
yarn add react-app-modules | ||
``` | ||
### Directory Structure | ||
Here is the directory structure used for the code in this tutorial, | ||
but feel free to use whatever structure works for you! | ||
![Directory Structure](media/tutorial/directory-structure.png) | ||
### Defining a Module | ||
Our `ICalculator` module will implement a single method, `sum`, | ||
which returns the arithmetic sum of a list of numbers. | ||
```typescript | ||
// src/modules/definitions/calculator.ts | ||
export interface ICalculator { | ||
sum(numbers: number[]): number; | ||
} | ||
``` | ||
### Defining the Symbols | ||
First, we are defining a `Calculator` symbol, which represents **any** | ||
implementation of the `ICalculator` interface. *Note that we have not | ||
coupled ourselves to an implementation. While not covered in this tutorial, | ||
the `createProvider` api be used to return a `DigitalCalculator` versus | ||
an `Abacus`, for example.* | ||
Next, we extend the internal `AppModules` type within `react-app-modules`. This | ||
bit of magic is what gives us complete type-safety for all the api methods. | ||
```typescript | ||
// src/modules/symbols.ts | ||
import { ICalculator } from './definitions/calculator'; | ||
export const Calculator = Symbol('Calculator'); | ||
declare module 'react-app-modules' { | ||
interface Types { | ||
AppModules: { | ||
[Calculator]: ICalculator; | ||
}; | ||
} | ||
} | ||
``` | ||
### Defining a Provider | ||
The provider is responsible for providing an implementation of `ICalculator`. | ||
To demonstrate module loading, we will emit an implementation after 1 second. | ||
The `createProvider` api is a convenient way to define a module implementation. | ||
*Note that this architecture allows a provider to dynamically provide an | ||
implementation for the `ICalculator` interface, as well as swap out for | ||
various `ICalculator` implementations during runtime, though that is out of | ||
scope for this tutorial. Also, the `createProvider` api can be used to indicate | ||
module dependencies, but that is not covered in this tutorial for the sake of brevity.* | ||
```typescript | ||
// src/modules/providers/provide-calculator.ts | ||
import { createProvider } from 'react-app-modules'; | ||
import { timer } from 'rxjs'; | ||
import { map } from 'rxjs/operators'; | ||
import { Calculator } from '../symbols'; | ||
export const provideCalculator = createProvider(Calculator, [], () => | ||
timer(1000).pipe( | ||
map(() => ({ | ||
sum: (numbers) => numbers.reduce((total, n) => total + n), | ||
})), | ||
), | ||
); | ||
``` | ||
### Defining an Example Component | ||
Now we will define an `Example` component that uses our new `Calculator` module. | ||
*Note that we are using the `useModule` hook provided by `react-app-modules`.* | ||
```typescript | ||
// src/components/example.tsx | ||
import React from 'react'; | ||
import { useModule } from 'react-app-modules'; | ||
import { Calculator } from '../modules/symbols'; | ||
const Example = () => { | ||
const calculator = useModule(Calculator); | ||
if (calculator === null) { | ||
return <span>Loading Calculator Module...</span>; | ||
} | ||
return <span>2 + 2 = {calculator.sum([2, 2])}</span>; | ||
}; | ||
export default Example; | ||
``` | ||
If you haven't been following along by typing, check this out: | ||
![Type Safety](media/tutorial/type-safety.png) | ||
Oh yeah. | ||
### Creating the Container / Context | ||
We are almost there! First, we use the `createContainer` api to compose | ||
the set of module symbols with their respective providers. Then, we | ||
supply the container to the `AppContext.Provider` component, which the | ||
`useModule` hook depends upon. Finally, we render our `Example` component | ||
within the `AppContext.Provider`. | ||
```typescript | ||
import React from 'react'; | ||
import { AppContext, createContainer } from 'react-app-modules'; | ||
import Example from './components/example'; | ||
import { provideCalculator } from './modules/providers/provide-calculator'; | ||
import { Calculator } from './modules/symbols'; | ||
const container = createContainer({ | ||
[Calculator]: provideCalculator, | ||
}); | ||
const App = () => ( | ||
<AppContext.Provider value={container}> | ||
<Example /> | ||
</AppContext.Provider> | ||
); | ||
export default App; | ||
``` | ||
### Checking the Results | ||
Time to fire that baby up. | ||
yarn start | ||
Observe that the module loads: | ||
![Module Loading](media/tutorial/module-loading.png) | ||
And then displays a result: | ||
![Finished Result](media/tutorial/finished-result.png) | ||
## Api | ||
TODO: More detailed overview of the Api methods. | ||
## Development | ||
@@ -51,0 +244,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
14053
262