reenhance-components v0.2.7
reenhance-components
A collection of React components which provide various functionality to child components in JSX/TSX. By using Render Props pattern, those components can be adopted declaratively just by surrounding children.
Works well when you create component which have some local states (e.g. radio group, toggle show/hide) or needs to show contents from APIs without propagating to global state (e.g. suggest, preview).
Installation and Usage
ES6/TS via npm
npm install reenhance-componentsCDN
For CDN, you can use unpkg: https://unpkg.com/reenhance-components/umd/index.min.js
The global namespace is ReenhanceComponents:
const { StateProvider, AsyncResolver, DebouncePropagator, ObjectHolder } = ReenhanceComponents;Documentation
Each components must be instantiated with initial parameters before using them in JSX/TSX.
AsyncResolver
Resolves async function and passes its result to children as props.
Parameters
| Property | Type | Required | Description |
|---|---|---|---|
| distinctKey | string | N | Name of prop to detect changes. Subject function is evaluated everytime value of the prop is changed. The default is 'subject'. |
| initialProps | object | N | Initial props for children |
Props
| Property | Type | Required | Description |
|---|---|---|---|
| subject | Function | Y | An async function which returns promise to resolve |
| (other props) | any | N | Arguments of subject |
Arguments of children
| Property | Type | Description |
|---|---|---|
| props | object | Resolved object from result of subject |
Example
const asyncFetch =
({ query }) =>
fetch(queryToUrl(query))
.then(res => res.json())
.catch(err => ({ error: err.toString() }));
const AlbumsAsyncResolver = AsyncResolver('query', { resultCount: 0, results: [] });
const Albums = ({ query }) => (
<AlbumsAsyncResolver subject={asyncFetch} query={query} >
{(props) => (
...
)}
</AlbumsAsyncResolver>
);StateProvider
Provides local state and updater to children as its props.
Parameters
| Property | Type | Required | Description |
|---|---|---|---|
| initialState | any | Y | Initial state |
Props
nothing
Arguments of children
| Property | Type | Description |
|---|---|---|
| state | object | Current state object |
| setState | Function | An updater for state. Takes new state as its argument |
Example
const ToggleState = StateProvider(false);
const Toggle = () => (
<ToggleState>
{({ state, setState }) => (
...
)}
</ToggleState>
);DebouncePropagator
Debounces props propagation for given milliseconds.
See Debounce of ReactiveX docs for more details.
Parameters
| Property | Type | Required | Description |
|---|---|---|---|
| initialProps | object | Y | Initial props for children |
Props
| Property | Type | Required | Description |
|---|---|---|---|
| time | number | Y | Debounce time in milliseconds |
| (other props) | any | N | Properties to propagete to children |
Arguments of children
| Property | Type | Description |
|---|---|---|
| props | object | Resolved object from result of subject |
Example
const SuggestDebounce = DebouncePropagator({ status: 'loading' });
const Suggest = ({ query }) => (
<SuggestDebounce time={'200'} query={query}>
{({ query, status }) => ( // Propagation of 'query' is debounced in 200ms
...
)}
</SuggestDebounce>
);ObjectWatcher
Watches a property of an object and passes the latest value as an argument to children.
Parameters
| Property | Type | Required | Description |
|---|---|---|---|
| targetObject | object | Y | Immutable object to watch its property change |
Props
| Property | Type | Required | Description | |
|---|---|---|---|---|
| watch | string | string[] | Y | Name(s) of property to watch |
| onChange | function | N | Called when the value of watching props is changed. Call signature is (newValue: any, oldValue: any, propName: string) => void |
Arguments of children
| Property | Type | Description |
|---|---|---|
| (any) | object | Proxied targetObject |
Example
const RefWatcher = ObjectWatcher(React.createRef());
const DivRef = () => (
<RefWatcher watch="current">
{divRef => (
<div ref={divRef}>Hello ref.{divRef.current ? divRef.current.toString() : null}</div>
)}
</RefWatcher>
);Compose (beta)
Composes multiple Components which have Render Props as their child.
Props
| Property | Type | Required | Description |
|---|---|---|---|
| childreni | Component | Y | A component which have Render Props as their child. |
| childrenn - 1 | Component | Y | A render function which receives all props from preceding components |
Example
const BooleanState = StateProvider<boolean>(true);
const NumericState = StateProvider<number>(3);
const MultiStateDiv = () => (
<Compose>
<BooleanState />
<NumericState />
{(b: StateAndUpdater<boolean>, n: StateAndUpdater<number>) => (
<div>
{b.state.toString()}:{n.state}
</div>
)}
</Compose>
);FAQ
- Q: Is this an alternative to Redux?
A: No. This module doesn't provide global state or flow pattern. - Q: Should I use this instead of Redux?
A: It depends. If the state or API response is local and per-instance, probably this module fits well. - Q: Is this better than HoCs?
A: Not sure. I think they are almost same. 😉 - Q: Can I rename arguments, 'state' and 'setState' of StateProvider?
A: Rename them in destructuring like({ state: isOpen, setState: setIsOpen }). - Q: Why
StateProviderpasses the state as a property of object? It's confusing.
A: One reason is for renaming. Another reason isstateandsetStateare inseparatable inStateProvider. TryObjectWatcherif you really don't want to usesetState. - Q: Why don't you make
AjaxResolver? It will be convenient. A: Requesting Ajax causes dependency to other APIs likefetch,fetchJsonp,Axios, etc. This module is intended to solve only common part of problems.
For contributors
This project aims these characteristics.
- declarative
- separation of view and logic
- can coexist with other modules
- works well with TypeScript
For myself
git push
npm publish5 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago