wcs-react-tools
v1.0.2
Published
a react-hook collection
Downloads
1
Readme
WCS React Tools
a react-hook collection
Index
StateController
A tiny but powerful state management for React. It is less than a hundred lines long and has no external dependencies.
function StateController (options)
Returns a controller object with these properties:
state
a more or less complex object holding the application stateactions
a optional list of actionssetState(newState)
a function for manipulating the stateuseState()
a react hook similar to the function of the same name from ReactaddListener(func)
a function for subscribing to state changesremoveListener(func)
a function for unsubscribing
Counter Demo
import React from "react";
import {StateController} from 'wcs-react-tools'
const controller = StateController({
initial: {
counter: 0,
counterId: 1,
children: []
},
actions: {
inc() {
this.setState(prev => ({ counter: prev.counter + 1 }));
},
remove(id) {
this.setState(prev => ({children: prev.children.filter(e => e !== id )}));
}
},
})
export default function App() {
const [state, setState] = controller.useState();
const {children,counterId} = state;
const addCounter = () => {
setState({
children: [...children, counterId],
counterId: counterId + 1,
});
};
return (
<div className="App">
<h1>Counter Demo</h1>
<button onClick={addCounter}>Add Counter</button>
<div className="container">
{children.map( id => <Counter key={id} id={id} />)}
</div>
</div>
);
}
function Counter(props) {
const {counter} = controller.useState()[0];
const {id} = props;
const remove = () => controller.actions.remove(id);
return (
<div className="Counter">
<span>Counter ({id}):{' '}{counter}</span>
{' '}
<button onClick={controller.actions.inc} >
+1 to global
</button>
{' '}
<button onClick={remove} >
remove
</button>
</div>
);
};
Hints
The StateController function accept a options object. Property options.initial is initial state. The state must be a object. Property options.action is an object with functions. The functions will bound to the resulting object, so you can use this.
The useState hook returns [state,setState] where both are the same as the controller properties.
The setState argument is either an object branch or a function that returns an object branch.
c = StateController({initial: {count:1, other: 'keep'}})
assert.deepEqual(c.state, {count:1, other: 'keep'})
// simple increment
c.setState( prev => ({count: prev.count + 1}))
assert.deepEqual(c.state, {count:2, other: 'keep'})
// todos example
c.state = {
todos: [
{ id: 1, text: 'Learn React', completed: false },
{ id: 2, text: 'Build an app with React', completed: false }
]
};
var nextState = draft => {
draft.todos.push({ id: 3, text: 'Test React', completed: true });
draft.todos[0].completed = true;
return draft;
};
var expected = {
todos: [
{ id: 1, text: 'Learn React', completed: true },
{ id: 2, text: 'Build an app with React', completed: false },
{ id: 3, text: 'Test React', completed: true }
]
};
c.setState( nextState );
assert.deepEqual(c.state, expected );
withStateController
A higher-order component (HOC) to connect a class component to StateController.
function withStateController (Component, controller)
returns wrapped component with state, setState and actions in props.
RemoteController
A tiny controller to controll a component's state from outside.
function RemoteController (initialProps = {})
returns the controller object.
useRemote
A React hook.
function useRemote (controller)
const [remoteProps, setRemoteProps] = useRemote (controller);
withRemote
A higher-order component (HOC) to connect a class component to RemoteController.
function withRemote (Component, controller)
returns wrapped component with state props injected from controller.
DragSort
A React helper hook to sort a list per drag and drop.
function DragSort (list, setList)
- list is the array to be sorted
- setList is the function to store reordered list
Function DragSort returns an object with all required functions and the React hook. The function dragProps of the object can inject all html attributes like draggable, onDragStart and so on.
Usage example:
import React from 'react';
import {ListGroup, ListGroupItem} from 'reactstrap';
import {DragSort} from 'wcs-react-tools';
export default function MyList (props) {
const [list,setList] = React.useState(['item 1','item 2','item 3']);
const drag = DragSort(list, setList); // create drag object
const items = list.map( (item,index) => { // create item JSX
var itemProps = {
key: index,
...drag.dragProps(index) // inject dragProps
}
return <ListGroupItem {...itemProps} >{item}</ListGroupItem> // return item JSX
});
return <ListGroup {...{style: {maxWidth: '20rem'}, ...props}} >
{items}
</ListGroup>;
}
useListSelect
A React hook to simplify the selection in lists.
- select one or more list items with mouse click
- select a range of items with mouse
- skip and select items bei name per keyboard
- auto select first item after mount
usage
function List({items}) {
const aSel = useListSelect({
length: items.length,
getSearchWord: index => items[index].name,
}, items);
return <ul>
{items.map( (item,index) => {
item.key = index + 1;
return (
<li key={item.key} {...
{
onDoubleClick: ev => onOpen(item, ev),
...aSel.itemProps(index),
}}
/>
{item.name}
</li>
)
})}
</ul>
}
The hook works with index, a value from 0 to list lenght - 1. The returned object supplies some properties and functions
selected
is a array of selected indexesselect
is a function to change the selectionfunction select(newSelection)
newSelection is a array of indexes, a single index or undefined to clear selectedisSelected
is a function to test if a index is selectedfunction isSelected(index)
itemProps(index)
is a function that returns an object whose properties are injected into jsx
options
length
length is the length of list. Alternatively, maxIndex can also be setmaxIndex
same as length-1multiselect
default is 'true'autoselect
default is 'false'.
Set 'true' to select the first item on mount.
The require the 'items' as second argument.keydisable
default is 'false', set 'true' to disable key down handlehandleKeyDown
default is 'undefined' set function for custom key down handlinggetSearchWord
default is 'null'.
Set it to a function that retuns a search word to enable a jump on keyboard press.
example:(index) => myItems[index].label
id
a id prefix used to scroll to search word
handleKeyDown example
handleKeyDown: (event,index) => {
if (event.key === 'Enter') {
console.log('Enter', index)
return true;
}
},