/react-cond

Lisp-Style conditional rendering in react.

Primary LanguageJavaScriptMIT LicenseMIT

react-cond

Usage | Examples | License


logo by Justin Mezzell

Lisp-Style conditional rendering in react.

Travis Coveralls David npm

Make conditional rendering in react simple and expressive. react-cond is implemented as a component, which takes n clauses as its children. Each clause is an array with a condition and a component. The first child-component, where the condition evaluates to true gets rendered in a Cond component. React-cond is designed to work great with FP-libraries like Ramda.

import { Cond, between, eq, T, Clause, Default } from 'react-cond';

<Cond value={angerLevel}>
	{[ eq(0), <span>sleepy</span> ]}
	{[ between(0, 20), <span>calm</span> ]}
	{[ between(20, 40), <span>angry</span> ]}
	{[ between(40, 41), <span>raging</span> ]}
	{[ T, <span>unknown anger level</span> ]}
</Cond>

// or as components

<Cond value={angerLevel}>
	<Clause test={eq(0)}><span>sleepy</span></Clause>
	<Clause test={between(0, 20)}><span>calm</span></Clause>
	<Clause test={between(20, 40)}><span>angry</span></Clause>
	<Clause test={between(40, 41)}><span>raging</span></Clause>
	<Default><span>unknown anger level</span></Default>
</Cond>

Usage

Installation | Importing | The Component `Cond` | Clauses | Helper Functions

Installation

$ npm install --save react-cond

Importing

React-cond exports the component Cond and a function T.

import { Cond, T } from 'react-cond';
// or the old way
var reactCond = require('react-cond');
var Cond = reactCond.Cond;
var T = reactCond.T;

The Component Cond

Cond is a react component, which controls rendering of its child components.

<Cond value={nr}>
  {[ T, <p key="always-true">always rendered</p> ]}
</Cond>

Cond has two props: value and compare.

value is the value which gets passed to each clause. compare is the default compare function for each clause.

Clauses

The Cond component wraps n clauses. A clause has either the following format: {[ condition, <Component /> ]} f.e. {[ x=> x > 0, <Positive /> ]} or is a Clause/Default component.

import { Cond, T } from 'react-cond';
// ...

<Cond value={nr}>
  {[ x => x > 0, <Positive /> ]}
  {[ x => x < 0, <Negative /> ]}
  {[ T, <Zero /> ]} // `T` always evaluates to true. see Helper Functions.
</Cond>

// or with Clause/Default
import { Cond, Clause, Default } from 'react-cond';
// ...

<Cond value={nr}>
  <Clause test={x => x > 0}><Positive /></Clause>
  <Clause test={x => x < 0}><Negative /></Clause>
  <Default><Zero /></Default>
</Cond>

Helper Functions

T | eq | isTrue | isFalse | isUndefined | isNull | not | gt | lt | gte | lte | between | and | or | value

The following helper functions are optional, but allow you to write even more expressive conditions for your clauses.

T

T

Can be used as an otherwise or else clause. It always evaluates to true.

import { Cond, T } from 'react-cond';
// or youe can import T as otherwise.
import { Cond, T as otherwise } from 'react-cond';

<Cond value={'_test_'}>
  {/* ... your clauses ... */}
  {[ T, <h1>otherwise</h1>]}
</Cond>

eq

eq([property:String], value:Any)

Condition to test if the value is equal (===) to a given value.

import { Cond, eq } from 'react-cond';

<Cond value={this.state.nr}>
  {[ eq(42), <h1>nr is 42</h1>]}
</Cond>

isTrue

isTrue([property:String])

Condition to test if the value is true.

import { Cond, isTrue } from 'react-cond';

<Cond value={true}>
  {[ isTrue, <h1>true</h1>]}
</Cond>

isFalse

isFalse([property:String])

Condition to test if the value is false.

import { Cond, isFalse } from 'react-cond';

<Cond value={false}>
  {[ isFalse, <h1>false</h1>]}
</Cond>

isUndefined

isUndefined([property:String])

Condition to test if the value is undefined.

import { Cond, isUndefined } from 'react-cond';

<Cond value={undefined}>
  {[ isUndefined, <h1>undefined</h1>]}
</Cond>

isNull

isNull([property:String])

Condition to test if the value is null.

import { Cond, isNull } from 'react-cond';

<Cond value={null}>
  {[ isNull, <h1>null</h1>]}
</Cond>

not

not(condition:Function)

Inverts a condition. Can be used to test if a value is not equal (!==) to a given value.

import { Cond, eq, not } from 'react-cond';

<Cond value={this.state.nr}>
  {[ not(eq(42)), <h1>nr isn't 42</h1>]}
</Cond>

gt

gt([property:String], value:Any)

Condition to test if the value is greater than (>) a given value.

import { Cond, gt } from 'react-cond';

<Cond value={this.state.nr}>
  {[ gt(42), <h1>nr greater than 42</h1>]}
</Cond>

lt

lt([property:String], value:Any)

Condition to test if the value is lower than (<) a given value.

import { Cond, lt } from 'react-cond';

<Cond value={this.state.nr}>
  {[ lt(42), <h1>nr lower than 42</h1>]}
</Cond>

gte

gte([property:String], value:Any)

Condition to test if the value is greater or equal than (>=) a given value.

import { Cond, gte } from 'react-cond';

<Cond value={this.state.nr}>
  {[ gte(42), <h1>nr greater or equal than 42</h1>]}
</Cond>

lte

lte([property:String], value:Any)

Condition to test if the value is lower or equal than (<=) a given value.

import { Cond, lte } from 'react-cond';

<Cond value={this.state.nr}>
  {[ lte(42), <h1>nr lower or equal than 42</h1>]}
</Cond>

between

between([property:String], start:Any, end:Any)

Condition to test if the value is between two given values.

import { Cond, between } from 'react-cond';

<Cond value={this.state.nr}>
  {[ between(1, 10), <h1>nr between 1 and 10</h1>]}
</Cond>

and

and(condition:Function, condition:Function)

Combine two conditions with a logical and (&&).

import { Cond, and, eq } from 'react-cond';

const startsWith = x => str => str.startsWith(x);
const endsWith = x => str => str.endsWith(x);

<Cond value={str}>
  {[ and(startsWith('-'), endsWith('-')), <h1>string starts and ends with a dash</h1>]}
</Cond>

or

or(condition:Function, condition:Function)

Combine two conditions with a logical or (||).

import { Cond, or, eq } from 'react-cond';

const startsWith = x => str => str.startsWith(x);
const endsWith = x => str => str.endsWith(x);

<Cond value={str}>
  {[ or(startsWith('-'), endsWith('-')), <h1>string starts or ends with a dash</h1>]}
</Cond>

value

value(property:String, condition:Function)

If your conditions depend on multiple values you can pass an object to the value prop and use value to access them.

<Cond value={{ val1:12, val2: 13 }}>
	{[ and(value('val1', eq(11)), value('val2', eq(12))), <h1>unexpected</h1>]}
	{[ and(value('val1', eq(12)), value('val2', eq(13))), <h1>expected</h1>]}
	{[ T, <h1>unexpected</h1>]}
</Cond>

Examples

Ramda | Multiple Values

Ramda

react-cond works great with libraries like Ramda.

import R, { __, T } from 'ramda';

const notEquals = R.compose(R.not, R.equals);
const gt11 = R.gt(__, 11);

<Cond value={10}>
  {[ notEquals(10), <h1>not 10</h1>]}
  {[ gt11, <h1>greater than 11</h1>]}
  {[ T, <h1>otherwise</h1>]}
</Cond>

Multiple Values

This example shows how you can make conditions which depend on more than one value.

import { Cond, eq, T as otherwise } from 'react-cond';

const List = React.createClass({
  // ...
  render() {
    const { items } = this.state;

    return (
      <ul>
        <Cond value={this.state}>
          {[ ({ isLoading }) => isLoading, <Spinner /> ]}
          {[ eq('hasErrors', true), <Error /> ]}
          {ifNoSearchResult}
          {[ otherwise, items ]}
        </Cond>
      </ul>
    );
  }
});

const ifNoSearchResult = [
  ({ noSearchResult, items }) => noSearchResult || items.length <= 0
  , <NotingFound />
];

License

MIT © Christoph Hermann