garfio
v0.2.0
Published
extending Hookleton Pattern namespaces and more
Downloads
19
Maintainers
Readme
Garfio is a module composed of several submodules that try to facilitate the use of the hookletons. A hookleton is a globalized React Hook, this means that once declared its namespace it is linked to a single state.
The Hookleton
library includes only the minimum core code needed to maintain state synchronization between "the users" of the hookleton, but was designed to be fully extensible. The submodules of Garfio
are extensions of this code to be able to use the same hookleton namespace with different states.
Garfio solves the problem of namespaces using several user-selectable approaches. In the future, more approaches could be added if relevant.
It is recommend take a look first to Hookleton package Doc
Benefits
- Small size
- Zero dependencies (only Hookleton that depends on React Hook)
- 👉 without using React Context
- 👉 not complex user memoizations needed. Out of the box performance
- Works in any environment that supports React Hook: React Native, React Server-Side Rendering (next.js), Proto Native, ...
Installation
# NPM
npm i garfio
# Yarn
yarn add garfio
External resources
included subModules
Hookleton API
Garfio re-export the Hookleton API. You do not need to install hookleton module explicitly if you want to use it. Just:
// createHook from Hookleton module
import { createHook } from 'garfio';
Container
module
Hookleton + Container
Container create different state scopes within the enclosing tags and without using React Context
API
createHook(useHook, ...initial?): useHookleton
Parameters
useHook
is the user provide Hookinitial
any number of params that useHook will accept
Returns
useHookleton
returned Hookleton. Called by non-host componentsuseHookleton.Container
Container component for enclosing tags scopesuseHookleton.get
function that get the current output of the Hookleton. For standalone use
usage Example
import { createHook } from 'garfio/container';
function counter(initial = 0) {
const [count, setCount] = useState(initial);
const increment = () => setCount(count + 1);
return [count, increment];
}
const useCounter = createHook(counter);
const CounterContainer = useCounter.Container;
function Button() {
const [, increment] = useCounter();
return <button onClick={increment}>+</button>;
}
function Count() {
const [count] = useCounter();
return <p>{count}</p>;
}
export default () => (
<CounterContainer initialArg={1}>
<Count />
<Button />
<CounterContainer initialArg={3}>
<Count />
<Button />
</CounterContainer>
</CounterContainer>
);
initial arguments API
Containers can be initialized in two ways:
initialArg
prop
initialArg is an array of arguments which is spread
to the Hook provided by the user. If the value is not an array then it is converted. To pass an array as a start element, it must be enclosed in an array too.
Below are examples of usage and automatic conversions.
Single argument example:
import { createHook } from 'garfio/container';
const useValue = createHook(useState);
const Container = useValue.Container;
export default () => {
return (
<Container initialArg={3}>
{
/* output number 3 */
useValue()[0]
}
<Container initialArg="three">
{
/* output string "three" */
useValue()[0]
}
</Container>
<Container initialArg={[[1, 2, 3]]}>
{
/* output array [1,2,3] in JSX */
useValue()[0]
}
</Container>
</Container>
);
};
Multiple arguments example:
import { createHook } from 'garfio/container';
const useReduced = createHook(useReducer);
const Container = useReduced.Container;
const reducer = (s, a) => s;
const initial = 0;
export default () => {
return (
<Container initialArg={[reducer, initial]}>
{
/* output number 0(initial) */
useReduced()[0]
}
</Container>
);
};
initial object properties
like props
When initializing hooks that use an initialization object it is possible to declare object properties
as props of the Container.
Example:
import { createHook } from 'garfio/container';
const useReduced = createHook(({ reducer, initial }) => useReducer(reducer, initial));
const Container = useReduced.Container;
export default () => {
return (
<Container reducer={(s, a) => s} initial={0}>
{
/* output number 0(initial) */
useReduced()[0]
}
</Container>
);
};
The Container API and its functionality is inspired by the constante package although React Context has not been used for its implementation
Store
module
Hookleton + Simple + Store
If in Container we use the enclosing tags to define different hookleton scopes, with Store
the scope is linked to a single object
API
Store creation
createStore(hook, ...initial?): Store
Parameters
hook
is the user provide Hookinitial
any number of params that hook will accept
initial
parameters from Store creation step has priority overinitial
parameters from Store use.- Do not pass any parameters in the Store creation if you want to initialize it within some Component (when you
use
the hookleton).- Remember that hookletons are global, so they are only initialized once, in the first component rendered. The other initializations will be ignored.
Returns
Store
sigle object (unique), with this interface:
{
get(): any;
delete(): boolean;
}
get()
for standalone store usage
Standalone refers to obtaining the current state of the hookleton from any part of the application, including outside the React components. This state is not updated automatically
delete()
for store delete. Returntrue
on sucess
Store use
useStore(store, ...initial?): any
Parameters
store
already exist storeinitial
any number of params that provided hook will accept
Returns
Return value is any value returned by the hook
usage Example
import { createStore, useStore } from 'garfio/store';
const one = createStore(useState, 1);
const two = createStore(useState, 2);
const three = createStore(useReducer);
const reducer = (s, a) => s;
const Values = () => {
const [v1, set] = useStore(one);
useStore(two);
const [v2] = two.get();
const [v3, dispatch] = useStore(three, reducer, 3);
// output: 1,2,3
return (
<span>
{v1},{v2},{v3}
</span>
);
};
export default () => <Values />;
The Store API and its functionality is inspired in packages like: shared-state-hook, react-hook-shared-state, reactn, react-shared-hooks, react-hookstore
Simple
module
Hookleton + Simple
Simple
module does not add anything new. It simply allows you to use a hookleton without being explicit about the component that will act as the host of the hookleton. In other words, you do not need to use the useHookleton.use()
API, just useHookleton()
API
createHook(useHook, ...initial): useHookleton
Parameters
useHook
is the user provide Hookinitial
any number of params that useHook will accept
initial params are required. Any param used in
useHookleton
are ignored.
Returns
useHookleton
returned Hookleton. Called by non-host componentsuseHookleton.get
function that get the current output of the Hookleton. For standalone use
usage Example
import { createHook } from 'garfio/simple';
// useCounter is a useState but global
const useCounter = createHook(useState, 0);
const Increment = () => {
const [, update] = useCounter();
const increment = () => update(s => s + 1);
return <button onClick={increment}>+</button>;
};
// The host component
const Value = () => {
const [count] = useCounter();
return <span>{count}</span>;
};
export default () => (
<div>
<Value />
<Increment />
</div>
);
more Examples
Examples page include:
- Nested Counters with "Container" page | source
- Counters 10x40 with "Store" page | source
- Counter with "Simple" page | source
for a deeper insight ...
Please read Hookleton Doc
Credits
author
- Félix A.A. <> @bySabi
Contributing
- Documentation improvement
- Feel free to send any PR