thram-stateless v1.1.1
thram-stateless
React components for Application and Component state management using render props and Context API
Install
npm install --save thram-statelessComponents
<Stateless />
Add dynamic behaviour to your components without using state.
| prop | type | description |
|---|---|---|
| value | Object | Component value |
| events | Object | beforeMount, afterMount, beforeChange, afterChange |
| reducer | function | Reducer function |
<StoreProvider />
Add dynamic behaviour to a group of components using a store that can be consumed by <Store />.
| prop | type | description |
|---|---|---|
| value | Object | Component value |
| events | Object | beforeMount, afterMount, beforeChange, afterChange |
| reducer | function | Reducer function |
| persistor | Object | Persistor API to perist data after change and rehydrate |
<Store />
Store consumer.
| prop | type | description |
|---|---|---|
| state | String | Key of the value you want to connect in the store |
| reducer | function | Reducer function |
Usage
Stateless
import React from 'react';
import { Stateless } from 'thram-stateless';
const DisplayDropDown = ({ isOpened, toggle }) => (
<div>
<div>
Menu <i onClick={toggle}>{isOpened ? '👆' : '👇'}</i>
</div>
{isOpened && (
<ul>
<li>Menu 1</li>
<li>Menu 2</li>
<li>Menu 3</li>
</ul>
)}
</div>
);
const DropDown = () => (
<Stateless value={{ isOpened: false }}>
{({ value, change }) => (
<DisplayDropDown
isOpened={value.isOpened}
toggle={() => change({ isOpened: !value.isOpened })}
/>
)}
</Stateless>
);Application Store
StoreProvider implements Sateless under the hood so they have similar APIs.
import React, { PureComponent } from 'react';
import { StoreProvider, Store } from 'thram-stateless';
const AppCounter = () => (
<Store state="counter">
{({ value, change }) => (
<div>
<h2>{value}</h2>
<button onClick={() => change(value + 1)}>Button</button>
</div>
)}
</Store>
);
class App extends PureComponent {
render = () => (
<StoreProvider value={{ counter: 6 }}>
<Counter />
</StoreProvider>,
);
}Events
StoreProvider and Stateless has a very simple event lifecyle: beforeMount,
afterMount, beforeChange, afterChange
const App = () => (
<StoreProvider
events={{
beforeMount: value => {
/* .. */
},
afterMount: (value, change) => {
/* ... */
},
beforeChange: (nextValue, prevValue) => {
/* ... */
},
afterChange: (nextValue, prevValue) => {
/* ... */
},
}}
>
<Counter />
</StoreProvider>
);const DropDown = () => (
<Stateless
value={{ isOpened: false }}
events={{
beforeMount: value => {
/* .. */
},
afterMount: (value, change) => {
/* ... */
},
beforeChange: (nextValue, prevValue) => {
/* ... */
},
afterChange: (nextValue, prevValue) => {
/* ... */
},
}}
>
{({ value, change }) => (
<DisplayDropDown
isOpened={value.isOpened}
toggle={() => change({ isOpened: !value.isOpened })}
/>
)}
</Stateless>
);Reducer
StoreProvider, Store and Stateless can all handle the reducer pattern to
reduce the value before update:
const ReducedStoreApp = () => (
<StoreProvider reducer={(state, value) => ({ counter: value.counter + 1 })}>
<Counter />
</StoreProvider>
);const ReducedGlobalCounter = () => (
<Store state="counter" reducer={(state, value) => value + 1}>
{({ value, change }) => (
<Display value={value} onClick={() => change(value + 1)} />
)}
</Store>
);const ReducedCounter = () => (
<Stateless
value={{ counter: 1 }}
reducer={(state, value) => ({ counter: value.counter + 1 })}
>
{({ value, change }) => (
<Display
value={value.counter}
onClick={() => change({ counter: value.counter + 1 })}
/>
)}
</Stateless>
);Persistor
You can pass a Persistor API to the StoreProvider to persist/rehydrate the data.
You can use our simple implementation createPeristor that uses localStorage/sessionStorage or you can implement yours.
The Persistor API should have the following structure:
{
get: () => { /* To rehydrate */ },
set: () => { /* To persist data */ },
remove: () => { /* To remove a value */ },
clear: () => { /* To destroy the persisted data */ },
}Example:
import React, { PureComponent } from 'react';
import { StoreProvider, Store, createPersistor } from 'thram-stateless';
const persistor = createPersistor('app');
const AppCounter = () => (
<Store state="counter">
{({ value, change }) => (
<div>
<h2>{value}</h2>
<button onClick={() => change(value + 1)}>Button</button>
</div>
)}
</Store>
);
class App extends PureComponent {
render = () => (
<StoreProvider persistor={persistor} value={{ counter: 6 }}>
<Counter />
</StoreProvider>,
);
}TODO
- Ask for feedback!
License
MIT © Thram