react-controllable-renderless v0.1.0
react-controllable-renderless
Inspired by react-powerplug, a set of 'pluggable' renderless components that provide logic for your 'dumb' components.
Unlike react-powerplug the state of these renderless components can also be optionally controlled.
Also:
- A Filter component.
 - The Focus component provides a 
focusfunction to focus on the target (using refs). 
Quick example
import { State } from 'react-controllable-renderless';
import { Pagination } from './components';
// State works exactly like react-powerplug
const StateExample = props =>
  <State
    { ...props }
    initial={{ offset: 0, limit: 10, totalCount: 200 }}
    render={ ({state, setState}) =>
      <Pagination {...state} onChange={offset => setState({ offset })} />
    }
  />
// But we can also control parts of its state, e.g. limit, by adding props
const ControlledExample = props =>
  <StateExample
    limit={props.limit}
    onStateChange={props.onStateChange}
  />Renderless components
See react-powerplug for an introduction to using renderless components.
Note: You must use a
renderprop not thechildrenprop.
Install
yarn add react-controllable-renderlessnpm i react-controllable-renderlessExamples
See the storybook.
Components
State
Props
| prop | type | default | description | 
|---|---|---|---|
initial | object | undefined | The initial state. | 
onStateChange | function(changes: object, state: object) | noop | This function is called any time the state is changed. | 
render | function(renderProps: object) | required | The render function. See below. | 
In addition any part of the state can be controlled by passing a prop with the same name. E.g. to control
state.age, pass in anageprop,<State age={} ... />, and useonStateChangeto detect whenageis trying to be changed.
Render props
| prop | type | description | 
|---|---|---|
state | object | The current state. | 
setState | function | State setter, same as setState from React.Component. | 
Filter
Filters an array of items using a filterFunc that takes a query and items as arguments and return the filteredItems.
The query is updated by passing a new query to the refine render prop function.
In addition, query can be optionally controlled by passing a query prop and using onQueryChange to detect internal changes to the query.
Props
| prop | type | default | description | 
|---|---|---|---|
defaultQuery | any | '' | The default query. | 
filterFunc | function(items: array, query: any) | required | A function to filter the items. | 
items | array(any) | [] | The items to filter. | 
query | any | undefined | optional control prop | 
onQueryChange | function(newQuery: any) | noop | This function is called when the query is changed. | 
render | function(renderProps: object) | required | The render function. See below. | 
Render props
| prop | type | description | 
|---|---|---|
filteredItems | array(any) | The filtered items. | 
query | any | The current query. | 
refine | function(newQuery: any) | This function takes a new query and updates the filteredItems. | 
Focus
Like react-powerplug's Focus but also has focus and blur methods that use refs internally to allow a target element's focus to be controlled.
Props
| prop | type | default | description | 
|---|---|---|---|
onBlur | function(event: SyntheticEvent) | noop | This function is called when the target is blurred. | 
onFocus | function(event: SyntheticEvent) | noop | This function is called when the target is focused. | 
render | function(renderProps: object) | required | The render function. See below. | 
targetRef | function(element) | noop | An optional property to pass a ref callback to the target. Useful for chaining Focus components. | 
Render props
| prop | type | description | 
|---|---|---|
blur | function | This function blurs the target. | 
focus | function | This function will cause the target element to gain focus. | 
focused | boolean | The current focus state of the target. | 
getTargetProps | function(additionalProps={}) | A function that returns the props for the target (the element we wish to focus). Takes an optional object argument of extra props to be merge in.Example: <input { ...getTargetProps({onFocus: <handleFocus>}) } />See this blog post on 'prop getters'. | 
Toggle
Props
| prop | type | default | description | 
|---|---|---|---|
initial | boolean | false | The initial/default state of the toggle. | 
on | bool | undefined | optional control prop | 
onToggle | function(newState: bool) | This function is called when a toggle occurs. | |
render | function(renderProps: object) | required | The render function. See below. | 
Render props
| prop | type | description | 
|---|---|---|
on | bool | The current state of the toggle. | 
toggle | function | Function that toggles the state. | 
TODO
- Tests
 - Add children prop functionality
 - Add 
composefunctionality - Add other react-powerplug components
 
Credits
I initially learnt about the power of renderless components and the 'render prop' pattern from downshift as well as the 'prop getter' pattern used in getTargetProps prop of the Focus component.
I also learnt more about these patterns from articles and courses by Michael Jackson and Ryan Florence.
And, of course, react-powerplug.
Thank you.