Skip to content

Commit

Permalink
new documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
easilyBaffled committed Oct 8, 2018
1 parent 044ca46 commit 6d55bba
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 31 deletions.
137 changes: 107 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
<p align="center">
<img alt="match-by" src="media/match-by.svg" width="144">
</p>
<p align="center">
<a href="https://nodei.co/npm/<package>/"><img src="https://nodei.co/npm/<package>.png"></a>
</p>
<h3 align="center">
Match
</h3>
Expand All @@ -15,43 +18,117 @@
This module was made with affection for but in no way trying to be a pattern matcher. We've already got that [on the way](https://github.com/tc39/proposal-pattern-matching). Instead it is made to replace ugly ternary.
It matches a test value to a simple key value. Simple in that the key must be a valid key in a object, so a primitive.

### Match against primatives

For example
```javascript
const word = 'number'
const traficLightDisplay = intersection === 'stop'
? 'red'
: intersection === 'yeild'
? 'yellow'
: intersection === 'go'
? 'green'
: 'yellow flashing';
```
becomes
```javascript
const intersectionSituation = 'stop';

const lightOptions = {
stop: 'red',
yeild: 'yellow',
go: 'green',
_: 'yellow flashing'
};

match( {
number: () => <p>1</p>,
boolean: () => <p>true</p>,
string: () => <p>"Hi"</p>,
}, word )
const traficLightDisplay = match( lightOptions, intersectionSituation );
```
> <p>1</p>
Though that situation could be cleared up with a mapper function. What a mapper couldn't cleanly handle for you would be something like

```jsx
const ViewType = user.developer
? <Debug ... />
: user.admin
? user.beta
? <Admin beta />
: <Admin />
: user.beta
? <Customer beta />
: <Customer />
```
With `match` it becomes

```jsx
const userTypeViewMatching = match( {
developer: () => <Debug ... />
adminBeta: () => <Admin beta />
admin: () => <Admin />
userBeta: () => <Customer beta />
_: () => <Customer />
} )

### Include default values against primatives
```javascript
const word = 'undefined!';

match( {
number: () => <p>1</p>,
boolean: () => <p>true</p>,
string: () => <p>"Hi"</p>,
_: () => <p>None of the above</p>
}, word )
const ViewType = ( { userCase } ) =>
userTypeViewMatching( {
...userCase,
adminBeta: userCase.admin && userCase.beta,
customerBeta: !userCase.admin && userCase.beta
} )
```
> <p>None of the above</p>

# Usage

### Match against boolean values in an object
```javascript
<Fetch lazy url="https://api.github.com/users/easilyBaffled">
{ ( fetchStates ) =>
match( {
data: ( { data } ) => <pre>{JSON.stringify(data, null, 2)}</pre>
loading: () => <h1>...Loading</h1>,
error: ({ error }) => <h1>{error.message}</h1>
}, fetchStates )
}
</Fetch>
<h3><code>match(matchClauses, testExpression, [options={}])</code></h3>
[source](./index.js#L111 "View in source")

Match a value against a set of keys and produce the associated value.
The value may be a primitive, in which case it is matched directly against the keys of the `matchClauses` object.
The value may also be an object in which case, the keys in the object, whose values are not empty are used to match against the `matchClauses`.

#### Arguments
1. `matchClauses` *(Object)*: an object who's keys will be matched against. A default value, who's key is indicated by defaultKey, can be provided in the case that there is no match
2. `testExpression` *(Object|boolean|number|string)*: a value that will be matched against the keys of matchClauses
3. `[options={}]` *(Object)*: allow the user to set the defaultKey and matchAll case;
4. `[options.defaultKey=_]` *(string)*: The key used for the default value in the matchClauses.
5. `[options.matchAll=false]` *(boolean)*: If true `match` will return an array of all matches otherwise it will return just the first match

#### Returns
*(undefined|&#42;): Returns undefined if there is no match, otherwise returns the matching value(s)*

#### Example
```js
const matchClauses = {
a: 1,
b: 2,
_: 'default' // <- '_' is the default `defaultKey`
};

match( matchClauses, 'a' )
// => 1

match( matchClauses, 'c' )
// => 'default'




// If the matching value is a function, it will be called with the `testExpression`
const matching = match( {
function: matchFunction,
object: matchObject,
_: v => v
}, typeof 0 )
// => 'number'




// Match can be partially applied with just the matchClauses ahead of time.
<Fetch lazy url="https://api.github.com/users/easilyBaffled">
{ // Fetch is a render prop that passes the fetch status (`{loading, data, error}`) to its child
match( {
data: ( { data } ) => <pre>{JSON.stringify(data, null, 2)}</pre>
loading: () => <h1>...Loading</h1>,
error: ({ error }) => <h1>{error.message}</h1>
} )
}
</Fetch>
```
1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,4 @@ const match = ( matchClauses, testExpression, options = {} ) => {
};

export default match;

17 changes: 16 additions & 1 deletion index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ check.expect = ( ...args ) => {
let checkOpt = {
numTests: process.env.TRAVIS
? 100
: 10
: 15
};

if( typeof last === "function" )
Expand Down Expand Up @@ -364,7 +364,22 @@ const usersTypes = [
{ type: 'customer', privilege: false },
];

test('Trafic Light Example', () => {
const intersectionSituation = 'stop';

const lightOptions = {
stop: 'red',
yeild: 'yellow',
go: 'green',
_: 'yellow flashing'
};

const traficLightDisplay = match( lightOptions, intersectionSituation );
expect( traficLightDisplay ).toBe( 'red' );
expect( match( lightOptions, 'yeild' ) ).toBe( 'yellow' );
expect( match( lightOptions, 'go' ) ).toBe( 'green' );
expect( match( lightOptions )() ).toBe( 'yellow flashing' );
})

/*
test( 'Reducer Example', () => { // Taken from https://redux.js.org/basics/reducers#splitting-reducers
Expand Down

0 comments on commit 6d55bba

Please sign in to comment.