$ npm install react-powerplug
React PowerPlug is a set of pluggable renderless components and helpers that provides different types of state and logics so you can use with your dumb components. It creates a state and pass down the logic to the children, so you can handle your data. Read about Render Props pattern.
import { State, Toggle } from 'react-powerplug'
import { Pagination, Tabs, Checkbox } from './MyDumbComponents'
<State initial={{ offset: 0, limit: 10, totalCount: 200 }}>
{({ state, setState }) => (
<Pagination {...state} onChange={(offset) => setState({ offset })} />
)}
</State>
<Toggle initial={true}>
{({ on, toggle }) => (
<Checkbox checked={on} onChange={toggle} />
)}
</Toggle>
// You can also use a `render` prop instead
<Toggle
initial={false}
render={({ on, toggle }) => (
<Checkbox checked={on} onChange={toggle} />
)}
/>
Note 1: This branch is unstable and is in active development.
To the latest stable version go to 0.1-stable branch
Note 2: This is a kind of a cheat sheet for fast search.
If you want a more detailed API Reference and examples for each component see full docs
Component | Component Props | Render Props | |
---|---|---|---|
STATE CONTAINERS |
|||
<State> | { initial, onChange } |
{ state, setState } |
:point_down: :books: |
<Toggle> | { initial, onChange } |
{ on, toggle, set } |
:point_down: :books: |
<Counter> | { initial, onChange } |
{count, inc, dec, incBy, decBy, set } |
:point_down: :books: |
<Value> | { initial, onChange } |
{ value, setValue, set } |
:point_down: :books: |
<Map> | { initial, onChange } |
{ set, get, over, values } |
:point_down: :books: |
<Set> | { initial, onChange } |
{ values, add, clear, remove, has } |
:point_down: :books: |
<List> | { initial, onChange } |
{ list, first, last, push, pull, sort, set } |
:point_down: :books: |
FEEDBACK CONTAINERS |
|||
<Hover> | { onChange } |
{ isHovered, bind } |
:point_down: :books: |
<Active> | { onChange } |
{ isActive, bind } |
:point_down: :books: |
<Focus> | { onChange } |
{ isFocused, bind } |
:point_down: :books: |
<Touch> | { onChange } |
{ isTouched, bind } |
:point_down: :books: |
<FocusManager> | { onChange } |
{ isFocused, blur, bind } |
:point_down: :books: |
FORM CONTAINERS |
|||
<Input> | { initial, onChange } |
{ set, value, bind } |
:point_down: :books: |
<Form> | { initial, onChange } |
{ input, values } |
:point_down: :books: |
OTHER |
|||
<Compose> | { components } |
depends on components prop | :point_down: :books: |
Name | |
---|---|
compose(...components) | :books: |
composeEvents(...objOfEvents) | :books: |
<State initial={{ isLoading: false, data: null }}>
{({ state, setState }) => (
<DataReceiver
data={state.data}
onStart={() => setState({ isLoading: true })}
onFinish={data => setState({ data, isLoading: false })}
/>
)}
</State>
<Toggle initial={true}>
{({ on, toggle }) => <Checkbox checked={on} onChange={toggle} />}
</Toggle>
<Counter initial={0}>
{({ count, inc, dec }) => (
<CartItem
productName="Lorem ipsum"
unitPrice={19.9}
count={count}
onAdd={inc}
onRemove={dec}
/>
)}
</Counter>
<Value initial="React">
{({ value, setValue }) => (
<Select
label="Choose one"
options={['React', 'Angular', 'Vue']}
value={value}
onChange={setValue}
/>
)}
</Value>
<Map initial={{ sounds: true, graphics: 'medium' }}>
{({ set, get }) => (
<Settings>
<ToggleCheck checked={get('sounds')} onChange={c => set('sounds', c)}>
Game Sounds
</ToggleCheck>
<Select
label="Graphics"
options={['low', 'medium', 'high']}
selected={get('graphics')}
onSelect={value => set('graphics', value)}
/>
</Settings>
)}
</Map>
<Set initial={['react', 'babel']}>
{({ values, remove, add }) => (
<TagManager>
<FormInput onSubmit={add} />
{values.map(tag => (
<Tag onRemove={() => remove(tag)}>{tag}</Tag>
)}
</TagManager>
)}
</Set>
<List initial={['Buy new shoes']}>
{({ list, pull, push }) => (
<Todo>
<TodoFormInput onSubmit={push} />
{list.map(todo => (
<TodoItem onDelete={() => pull(i => i === todo)}>
{todo}
</TodoItem>
)}
</Todo>
)}
</List>
<Hover>
{({ isHovered, bind }) => (
<div {...bind}>
You are {isHovered ? 'hovering' : 'not hovering'} this div.
</div>
)}
</Hover>
<Active>
{({ isActive, bind }) => (
<div {...bind}>
You are {isActive ? 'clicking' : 'not clicking'} this div.
</div>
)}
</Active>
<Touch>
{({ isTouched, bind }) => (
<div {...bind}>
You are {isTouched ? 'touching' : 'not touching'} this div.
</div>
)}
</Touch>
<Focus>
{({ isFocused, bind }) => (
<div>
<input {...bind} placeholder="Focus me" />
<div>You are {isFocused ? 'focusing' : 'not focusing'} input.</div>
</div>
)}
</Focus>
<Input initial="hello world">
{({ bind, value }) => (
<div>
<ControlledInput {...bind} />
<div>You typed {value}</div>
</div>
)}
</Input>
<Form initial={{ subject: '', message: '' }}>
{({ input, values }) => (
<form
onSubmit={e => {
e.preventDefault()
console.log(values)
}}
>
<ControlledInput placeholder="Subject" {...input('subject').bind} />
<ControlledTextArea placeholder="Message" {...input('message').bind} />
<Submit>Send</Submit>
{/*
input(id) => { bind, set, value }
*/}
</form>
)}
</Form>
If you want to avoid 'render props hell' you can compose two or more components in a single one.
:books: For complete guide, see docs
import { Compose } from 'react-powerplug'
<Compose components={[Toggle, Counter]}>
{(toggle, counter) => (/* ... */)}
</Compose>
import { compose } from 'react-powerplug'
const ToggleCounter = compose(
<Counter initial={5} />,
<Toggle initial={false} />
)
<ToggleCounter>
{(toggle, counter) => (
<ProductCard {...} />
)}
</ToggleCounter>
yarn add react-powerplug
npm i react-powerplug
<script src="https://unpkg.com/react-powerplug/dist/react-powerplug.min.js"></script>
exposed as ReactPowerPlug
You can help improving this project sending PRs and helping with issues.
Also you can ping me at Twitter
© 2010 - cnpmjs.org x YWFE | Home | YWFE